Getting number of ITEMS in an array C# - c#

I need to insert a string (from one window(QueryBuilder)) into an array(of another window(Main)).
In the Main i have a method as
public void DisplayCalcQuery(string argFromQueryBuilder)
{
int itemsInUserBuiltQueries = UserBuiltQueries.Count();
UserBuiltQueries[itemsInUserBuiltQueries] = argFromQueryBuilder.ToString();
//displayng the user built query(queries) on the stack panel meant to display it.
foreach (string query in UserBuiltQueries)
{
CheckBox checkQueries = new CheckBox() { Content = query };
stackPanel1.Children.Add(checkQueries);
checkboxes.Add(checkQueries);
}
}
Where UserBuiltQueries is declared as
string[] UserBuiltQueries;
However when from the other window i do
backscreen.DisplayCalcQuery(ttextBox1.Text.ToString()); //where backscreen is the Main
The argument is passed well but i get an error as
{"Value cannot be null.\r\nParameter name: source"}
What did I do wrong ?

These lines are wrong
int itemsInUserBuiltQueries = UserBuiltQueries.Count();
UserBuiltQueries[itemsInUserBuiltQueries] = argFromQueryBuilder.ToString();
Arrays start at index zero and end at index (Count - 1), so, if UserBuiltQueries.Count() returns 10 you could use indexes from 0 to 9. Essentially, using index 10, you are adding a new string outside the end of the array.
However, if your requirements force you to expand the array, it is better and more easy to code if you use a List<string> instead. Adding new elements will be a lot more easier and you could still use the List as an Array for common tasks.
List<string> UserBuiltQueries = new List<string>();
.....
public void DisplayCalcQuery(string argFromQueryBuilder)
{
UserBuiltQueries.Add(argFromQueryBuilder);
//displayng the user built query(queries) on the stack panel meant to display it.
foreach (string query in UserBuiltQueries)
{
CheckBox checkQueries = new CheckBox() { Content = query };
stackPanel1.Children.Add(checkQueries);
checkboxes.Add(checkQueries);
}
}
By the way, you should stop to unnecessarily convert a string to a string. You pass a ttextBox1.Text.ToString() but ttextBox1.Text is already a string. Inside the method the parameter argFromQueryBuilder is already a string and there is no need to convert to a string

Instead of using string[] for UserBuildQueries, use List. When you need it as an array, you can simply say: UserBuildQueries.ToArry()
Rewrite the function to
public void DisplayCalcQuery(string argFromQueryBuilder)
{
UserBuiltQueries.Add(argFromQueryBuilder.ToString());
//displayng the user built query(queries) on the stack panel meant to display it.
foreach (string query in UserBuiltQueries)
{
CheckBox checkQueries = new CheckBox() { Content = query };
stackPanel1.Children.Add(checkQueries);
checkboxes.Add(checkQueries);
}
}

In c# but I think in all programming language indexis start from 0:
so if an array has length or count =1 the index is 0 array[0], array.lenght==1
int itemsInUserBuiltQueries = UserBuiltQueries.Count()-1;
UserBuiltQueries[itemsInUserBuiltQueries] = argFromQueryBuilder.ToString();
And double check that your array is initialized before using it!

Related

List of strings stored as values in dictionary C#

I have a testing framework that needs to be updated to include testing in Spanish. I have a CSV file that contains the field label, english text, and Spanish text. I've decided to use a dictionary to store the field label as the key and the values would be a list of strings for Spanish and English text.
private List<string> ReadTranslationCsv()
{
var pathToCSV = #"C:\Location";
Dictionary<string, List<string>> translations = new Dictionary<string, List<string>>();
string label, englishText, spanishText;
using (TextReader fileReader = File.OpenText(pathToCSV))
{
var csv = new CsvReader(fileReader);
csv.Configuration.HasHeaderRecord = false;
while (csv.Read())
{
for (int i = 0; csv.TryGetField<string>(i, out label);)
{
List<string> Spanglish = new List<string>();
csv.TryGetField<string>(i + 1, out englishText);
Spanglish.Add(englishText);
csv.TryGetField<string>(i + 2, out spanishText);
Spanglish.Add(spanishText);
if (label != "")
{
translations.Add(label, Spanglish);
}
i = i + 3;
}
}
}
}
I want to be able to search within the list of values to see if anything matches some string of text. I'm not sure how to search the lists that are within the dictionary, none of the default methods or properties are working.
I'm using the below code but this will return me a bool, which is not what I need, I need the list value that matches the elementWithText
public void GivenElementMatches(string elementWithText)
{
if (Config.Language == "Spanish")
{
var list = new List<string> { elementWithText };//must create list in order to pass text to any translations methods
Hooks.translations.ContainsValue(list); // Even though the labels are the key, I need to search for the english text which is index 1 of the list and all values should be returned
}
//TODO
}
My suggestion would be to use a Dictionary with a class you create, inside that class you can have a compare function.
The advantage of this method is you may add more language equivalents later and only have to change your model.
Please note, this code is not complete and you will have to bug check and alter it to suit.
Dictionary <string, LangEquivalents> model;
public KeyValuePair<string, LangEquivalents> findField(string input)
{
return model.First(x=>x.Value.Comparison(input));
}
You could also make it a comparable object type and just use model.First(x=>x.Value == input));

Combining Lists using Concat

I have some code that's main purpose is to combine multiple like lists into one master list to return with the View.
ActivityAuditDetails searchParams = new ActivityAuditDetails();
ActivityAuditDetails finalResults = new ActivityAuditDetails();
List<string> finalChangedColumns = new List<string>();
List<string> finalOldValues = new List<string>();
List<string> finalNewValues = new List<string>();
string finalAuditAction = string.Empty;
List<int> auditKeys = AuditIdentityId.Split(',').Select(int.Parse).ToList();
string url = "/Audit/GetActivityAuditDetails";
try
{
foreach (int auditKey in auditKeys)
{
searchParams.AuditIdentityId = auditKey;
ActivityAuditDetails result = // SOME METHOD THAT RETURNS RESULTS AS IT SHOULD;
finalChangedColumns.Concat(result.ChangedColumns);
finalAuditAction = result.AuditAction;
finalOldValues.Concat(result.OldValues);
finalNewValues.Concat(result.NewValues);
}
finalResults.ChangedColumns = finalChangedColumns;
finalResults.AuditAction = finalAuditAction;
finalResults.OldValues = finalOldValues;
finalResults.NewValues = finalNewValues;
}
catch (Exception e)
{
e.ToLog();
}
return View(finalResults);
I can see that the result object is populated as it should be in the debugger. I thought the Concat method would work to combine the lists, but my final values in the foreach loop never get update\incremented ( the list count remains zero ).
Is there another way to accomplish this, or am I having a morning brain fart? My question was not about the differences, as I was aware of them. I just had a momentary lapse of reason.
You likely want to use AddRange rather than Concat.
The former adds the data directly to the List. The latter concatenates data into a new IEnumerable.
But because you are not assigning the result of Concat to anything (i.e. var g = finalChangedColumns.Concat(result.ChangedColumns);) your Concat calls do effectively nothing.
List<T>.AddRange(IEnumerable<T> collection) (link to info) probably does what you're looking for, right?
Adds the elements of the specified collection to the end of the List.
From documentation:
string[] input = { "Brachiosaurus",
"Amargasaurus",
"Mamenchisaurus" };
List<string> dinosaurs = new List<string>();
dinosaurs.AddRange(input);
//The list now contains all dinosaurs from the input string array

Deleting an array element while moving others down?

I'm really new to programming, so take this with a grain of salt.
I've made 2 arrays that correspond to eachother; One is a Name array and one is a Phone Number array. The idea is that the spot [1] in NameArray corresponds to spot [1] in the PhoneArray. In other words, I need to keep these 'pairings' in tact.
I'm trying to make a function that deletes one of the spots in the array, and shifts everything down one, as to fill the space left empty by the deleted element.
namearray = namearray.Where(f => f != iNum).ToArray();
is what I've tried, with iNum being the number corresponding to the element marked for deletion in the array.
I've also tried converting it to a list, removing the item, then array-ing it again.
var namelist = namearray.ToList();
var phonelist = phonearray.ToList();
namelist.Remove(txtName.Text);
phonelist.Remove(txtPhone.Text);
namearray = namelist.ToArray();
phonearray = phonelist.ToArray();
lbName.Items.Clear();
lbPhone.Items.Clear();
lbName.Items.AddRange(namearray);
lbPhone.Items.AddRange(phonearray);
with txtName.Text and txtPhone.Text being the strings for deletion in the corresponding list boxes.
Can someone suggest a better way to do it / What I'm doing wrong / How to fix?
Thanks guys
-Zack
A better way would be to have an array of a class that contains a Name and Phone Number object:
public class PersonData
{
public string Name { get; set; }
public string Phone { get; set; }
}
public PersonData[] data;
That way, instead of keeping two arrays in sync, it's one array with all the appropriate data.
Try a loop through both arrays, moving the values of each down an index each time.
Start the loop at the index of the value you want to delete. So you would find the IndexOf(T) the value you want, storing it as deleteIndex and run the loop starting from that index.
When you hit the end of the array, set the last value as null or string.Empty (depending what value type the array holds).
A bit like this:
var deleteIndex = namearray.IndexOf("TheStringYouWantToDelete");
for (int i = deleteIndex; i < namearray.Length; i++)
{
if (i == namearray.Length - 1) // The "last" item in the array.
{
namearray[i] = string.Empty; // Or null, or your chosen "empty" value.
phonearray[i] = string.Empty; // Or null, or your chosen "empty" value.
}
else
{
namearray[i] = namearray[i+1];
phonearray[i] = phonearray[i+1];
}
}
This will work for deleting and moving values 'down' in index.
You could also rewrite the code for moving them the other way, as it would work similarly.
Reordering them completely? Different ball game...
Hope this helps.
If the namearray and phonearray contain strings and you know the index of the element to remove (iNum) then you need to use the overload of the Where extension that takes a second parameter, the index of the current element in the evaluation
namearray = namearray.Where((x, y) => y != iNum).ToArray();
However the suggestion to use classes for your task is the correct one. Namearray and Phonearray (and whatever else you need to handle in future) are to be thought as properties of a Person class and instead of using arrays use a List<Person>
public class Person
{
public string FirstName {get; set;}
public string LastName {get; set;}
public string Phone {get; set;}
}
List<Person> people = new List<Person>()
{
{new Person() {FirstName="Steve", LastName="OHara", Phone="123456"}},
{new Person() {FirstName="Mark", LastName="Noname", Phone="789012"}}
};
In this scenarion removing an item knowing the LastName could be written as
people = people.Where(x => x.LastName != "OHara").ToList();
(or as before using the index in the list of the element to remove)
people = people.Where((x, y) => y != iNum).ToArray();
The other answers provide some better design suggestions, but if you're using ListBoxes and want to stick with arrays, you can do this to synchronize them:
int idx = lbName.Items.IndexOf(txtName.Text);
if (idx > -1)
{
lbName.Items.RemoveAt(idx);
lbPhone.Items.RemoveAt(idx);
}
namearray = lbName.Items.Cast<string>().ToArray<string>();
phonearray = lbPhone.Items.Cast<string>().ToArray<string>();
Use a dictionary instead.
Dictionary<string, string> phoneBook = new Dictionary<string, string>();
phoneBook["Foo"] = "1234567890";
phoneBook["Bar"] = "0987654321";
phoneBook.Remove("Bar");

C# Converting List to 2d list and adding additional values

Hello need some assistance with this issue. Hopefully i can describe it well.
I have a parser that goes though a document and find sessionID's, strips some tags from them and places them into a list.
while ((line = sr.ReadLine()) != null)
{
Match sID = sessionId.Match(line);
if (sID.Success)
{
String sIDString;
String sid = sID.ToString();
sIDString = Regex.Replace(sid, "<[^>]+>", string.Empty);
sessionIDList.Add(sIDString);
}
}
Then I go thought list and get the distinctSessionID's.
List<String> distinctSessionID = sessionIDList.Distinct().ToList();
Now I need to go thought he document again and add the lines that match the sessionID and add them to the list. This is the part that I am having issue with.
Do I need to create a 2d list so I can add the matching log lines to the corresponding sessionids.
I was looking at this but cannot seem to figure out a way that I could copy over my Distinct list then add the Lines I need into the new array.
From what I can test it looks like this would add the value into the masterlist
List<List<string>> masterLists = new List<List<string>>();
Foreach (string value in distinctSessionID)
{
masterLists[0].Add(value);
}
How do I add Lines I need to the corresponding Masterlist. Say masterList[0].Add value is 1, how do i add the lines to 1?
masterList[0][0].add(myLInes);
Basically i want
Sessionid1
-------> related log line
-------> Related log line
SessionID2
-------> related log line
-------> related log line.
So on and so forth. I have the parsing all working, it's just getting the values into a 2nd string list is the issue.
Thanks,
What you can do is, simple create a class with public properties, and make list of that custom class.
public class Session
{
public int SessionId{get;set;}
public List<string> SessionLog{get;set;}
}
List<Session> objList = new List<Session>();
var session1 = new Session();
session1.SessionId = 1;
session1.SessionLog.Add("description lline1");
objList.Add(session1);
Here is one way to do it:
public class MultiDimDictList: Dictionary<string, List<int>> { }
MultiDimDictList myDictList = new MultiDimDictList ();
Foreach (string value in distinctSessionID)
{
myDictList.Add(value, new List<int>());
for(int j=0; j < lengthofLines; j++)
{
myDictList[value].Add(myLine);
}
}
You would need to replace lengthofLines with a number to indicate how many iterations of lines you have.
See Charles Bretana's answer here

how to dissect string values

How can I dissect or retrieve string values?
Here's the sample code that I'm working on now:
private void SplitStrings()
{
List<string> listvalues = new List<string>();
listvalues = (List<string>)Session["mylist"];
string[] strvalues = listvalues.ToArray();
for (int x = 0; x < strvalues.Length; x++)
{
}
}
Now that I'am able to retrieve list values in my session. How can I separately get the values of each list using foreach or for statement?
What I want to happen is to programmatically split the values of the strings depending on how many is in the list.
If you have a list of string values, you can do the following:
private void SplitStrings()
{
List<string> listValues = (List<string>) Session["mylist"];
// always check session values for null
if(listValues != null)
{
// go through each list item
foreach(string stringElement in listValues)
{
// do something with variable 'stringElement'
System.Console.WriteLine(stringElement);
}
}
}
Note that I test the result of casting the session and that I don't create a new list first-off, which is not necessary. Also note that I don't convert to an array, simply because looping a list is actually easier, or just as easy, as looping an array.
Note that you named your method SplitStrings, but we're not splitting anything. Did you mean to split something like "one;two;three;four" in a four-element list, based on the separator character?
I'm not sure what you're trying to obtain in this code, I don't know why you're converting your List to an Array.
You can loop through your listValues collection with a foreach block:
foreach(string value in listValues)
{
//do something with value, I.e.
Response.Write(value);
}
I don't know what's in the strings but you can start by simplifying. There is no point allocating a new List if you're going to overwrite it immediately.
private void SplitStrings()
{
List<string> list = (List<string>)Session["mylist"];
foreach(string value in list)
{
}
}
List listvalues = (List)Session["mylist"];
foreach (string s in listvalues)
{
//do what you want with s here
}

Categories

Resources