Why am I getting ArgumentOutOfRangeException in Lists? - c#

I am using List of Lists in my project. When i run program i get ArgumentOutOfRangeException. But there is no range specified in list.
I declared list like this:
public static List<List<string>> list = new List<List<string>>();
Now i want to add my name in the first "list" which is in the List of lists.
list[0].Add("Hussam"); //Here i get ArgumentOutOfRange Exception.
What should I do now?

But there is no range specified in list
No, there's an index specified (as an argument), and that's what's out of range. Look at your code:
list[0].Add("Hussam");
That's trying to use the first list in list - but is list is empty, there is no first element. The range of valid arguments to the indexer is empty, basically.
So first you want:
list.Add(new List<string>());
Now list[0] will correctly refer to your empty List<string>, so you can add "Hussam" to it.

You want to add an item to the first item in an empty list... That isn't going to work. First, add the list inside the other list:
public static List<List<string>> list = new List<List<string>>();
List<string> innerList = new List<string>();
list.Add(innerList);
innerList.Add("Hussam");

Why are you creating a list of a list? Wouldn't List suffice? What is happening here is the inner list is not being initialized.
list.Add(new List<string>());
list[0].Add("Jimmy");

In this case ocurred an exception because you tried acess an index which not exists, then you must add an inner initial list, which could be done follows:
list.Add(new new List<string>());
Or, if you want add an first name directly:
list.Add(new new List<string>(){"Hussam"});

Ok so first, you have to understand that the "index" only comes after the value has been declared. Lists behave different. They are not like arrays. You get the index in which you want to store the item and when you do that, you use the code array[index] = value;.
But in a List, to give a value to a completely new item, you use the method Add(value).
So here's a reminder: Systems.Collections.Generic.List<> has nothing to do with array[ ]s

You cannot access list[0] as there is no item at index 0. The list is empty.
You need to add a new List like this:
list.Add(new List<string> { "Hussam" });
or, assign a list to index 0 and then add to it as per your posted code:
list.Add(new List<string>());
list[0].Add("Hussam");
If you don't always know if the list will be be empty or not you can use FirstOrDefault (a LINQ method) to check if there is any entry at index 0 and assign one if not, otherwise use the existing inner list:
var innerList = list.FirstOrDefault();
if (innerList == null)
{
innerList = new List<string>();
list.Add(innerList);
}
innerList.Add("Hussam");

The problem is, your nested list hasn't been initialized, with anything.
So, calling the first item of the nested list is correctly telling you there is nothing in it.
To verify:
int superlistCounter = 1;
int sublistCounter = 1;
foreach(var sublist in list)
{
Console.WriteLine("Now in List #" + superlistCounter);
foreach(var item in sublist)
{
Console.WriteLine("List item #" + sublistCounter + ": " + item)
}
}
The output will be:
Now in List #1
It sounds like you're expecting:
Now in List #1
List Item #1: Hussam
To fix this, simply initialize your list!
public static List<List<string>> list = new List<List<string>>();
// ...
List<string> subList1 = new List<string>();
list.Add(subList1);
subList1.Add("Hussam");

Related

C# dictionary value is updating automatically

In my recent project im trying to make a dictionary with key as a string and value as List of string(List) and adding value in dictionary using for loop ,
but the problem is that after first iteration when I Update the List for second iteration it is automatically changing in the first key value pair.
for example in first iteration it is saving key as apple and value as list {cucumber,chilli,tomato,apple} its fine but after first iteration when i update list to {cucumber,chilli,tomato,apple,mango} and saving it to second key mango it is also updating the first value to {cucumber,chilli,tomato,apple,mango}.
var mylist = new List<string>()
{
"cucumber",
"chilli",
"tomato"
};
var yourlist = new List<string>()
{
"apple",
"mango",
"banana"
};
var dict = new Dictionary<string, List<string>>();
foreach (var i in yourlist)
{
mylist.Add(i);
dict.Add(i,mylist);
}
foreach(var d in dict.Keys)
{
foreach(var l in dict[d])
{
Console.WriteLine(l);
}
}
The dictionary entries' Value properties are always the same list, so anything you do to one, ends up showing in all of them (because there is only one)
Take a look at the code below; if you understand why a and b here both show the same change, then you should understand that your dictionary scenario is essentially the same
var list = new List<string>(){ "hello", "world" };
var a = list;
var b = list;
a.Add("there");
Console.Write(b.Count); //shows 3
If you don't understand why a, b and list above all refer to the same list, then drop a comment and I'll add some more explanation
As to what you should do about your "issue", it's not entirely clear to me what you're hoping to do but if you made sure that each key in the dictionary associated with a new list rather than the same one, then changes to one key's list would not show in other keys' lists:
dict.Add(i, new List<string>(mylist));
This makes a new list per key, and initializes the new list with the items present in mylist at the time (my list grows each pass of the loop)

add two strings to two dimensional list

i want to add in two set of strings to one list
i receive error that i cant use add
List<List<String>> lastmodified1 = new List<List<String>>();
lastmodified1.Add(new List<String>());
foreach (string filenamelocal in files)
{
string name = Path.GetFileName(filenamelocal);
lastmodified1[0][1].Add(Convert.ToString(filenamelocal));
lastmodified1[0][0].Add(Convert.ToString(File.GetLastAccessTime(filenamelocal)));
}
you target the list with the first index
lastmodified1[0].Add(Convert.ToString(filenamelocal));
lastmodified1[0].Add(Convert.ToString(File.GetLastAccessTime(filenamelocal)));
with the index [0] you are target the list, because the first List is implicit.
so with
lastmodified1[0].Add(Convert.ToString(filenamelocal)); //this is accessing to the List inside the First list
you are accesing to the second List inside from the first List.
with the second index you're accessing to the value of the second list, in this case String, and you can get the method add because strings dont have
lastmodified1[0][0] //this access to string value

copy a specific item from one list to a specific place of another list by c#

I have two lists like list1 and list2 both from type int. now I want to copy the item of index (2) in my list 1 and put it instead of item with index (3) in my second list. how is it possible?
list<int> list1 = new list<int>(){1,2,4,5,7,8,9,11};
list<int> list2 = new list<int>(){22,33,44,55,66};
I want to have the result as:
{22,33,44,4,66}
I did like this:
list2[3]=list1[2];
but I have error of "index out of range"
I will really appreciate if help me.

Add element to list before specific element

I have a list of items, lets say 100 items. I need to add another element before the existing element that matches my condition. What is the fastest way and the most performance optimized to do this?
ie.:
foreach (var i in myList)
{
if (myList[i].value == "myValue")
{
myList[i-1] add ("someOtherValue")
}
}
Maybe i should use other container?
First you could find the index of your item using FindIndex method:
var index = myList.FindIndex(x => x.value == "myvalue");
Then Insert at the right point:
myList.Insert(index,newItem);
Note that inserting at a given index pushes everything else forward (think about finding your item at index 0).
Consider using a LinkedList<T>. It has the advantage that inserting or removing items does not require shifting any items. The disadvantage is that items cannot be accessed randomly. You have to traverse the list starting at the first or last item in order to access the items.
myList.Insert(myList.IndexOf("myValue") - 1, "someOtherValue");
You should probably check to make sure myvalue exists first, and it is not in index 0.
int index = myList.IndexOf("myValue");
if (index >= 0)
myList.Insert(index, "myNewValue");
By the way, you should not modify your own collection or list while iterating with for-each (as in your code above).
I presume the list is an array - in which case have you tried doing this with Linq?
string[] mylist = new string[100];
// init the list
List<string> list = keys.ToList();
list.Insert(1,"somethingelse");
mylist = list.ToArray(); // convert back to array if required
if it is a List to begin with, you can skip the conversions and use Insert directly.

iterating over a collection and removing ones I dont want

I have a problem with the following. I have a collection:
Collection<Vehicle> list = new Collection<Vehicle>();
code = 1,2,3, Description = "aaa"
code = 10,438,13, Description = "bbb"
code = 81,8623,362, Description = "ccc"
code = 163,4312,53, Description = "ddd"
...
But I only care about some of them.. The list I care about is here, i.e. codesCareAbout = "1|2|3|163|4312|53"
I need to iterate through the collection and either deleting the Vehicle I don't care about, or cherry picking into another list containing the Vehicles I care about?
Any suggestions?
Many thanks,
James
You can iterate your list backwards, and use RemoveAt using the for index to remove from the list:
for (int i = list.Count - 1; i >= 0; i--)
{
Foo item = list[i];
if (IsFoobar(item))
list.RemoveAt(i);
}
Counting backwards is required so that you don't mutate your index counting as you go, using a for loop is required because you cannot mutate a list being enumerated with an enumerator.
Alternatively, do as you suggested, populate into an empty list the stuff you want - however, usage depends on whether you need to modify the list you are given or can make a new list.
Assuming that Vehicule has Code (string) property and Description property (question is not clear !).
1/ Clone the list : var clone = list.ToList();
2/ Iterate and decide if current item is interesting :
foreach(var item in clone)
{
if (! IsInteresting(item))
list.Remove(item);
}
3/ IsInteresting could be, for example :
foreach(var code in item.Code.Split(','))
{
if (codesCareAbout.Split('|').Contains(code))
return true;
}
Filtering the list with linq produces the cleanest code:
var interestinglist = list.Where(v=> v.IsInteresting(v));
IsInteresting can be implemented as
codesIcareAbout.Intersect(v.Codes).Any();
this assumes both fields are collections rather than strings, but that is easily fixed with a call to string.Split().

Categories