Iterating through generic collections
I have a method that uses two generic lists. The first is a 'catch-all' list that holds id's for all projects, and inside the loop a test is run that adds the project weight to the other list. If this was all, everything would be ok, but it's not. I have to iterate through this for each user id and add their project weights to the same index of the list. So, instead of using the Add() method, I need to add amounts to the list's elements by index. However, I keep getting an ArgumentOutOfRangeException. The index is 0, and I'm not understanding where this is coming from.
JurePosted Oct 27, 2010, 9:08 PM
Mahesh ChandPosted Oct 27, 2010, 5:24 PM
I agree with Sam though. If you look at Collections and Generic namespace, you can find pretty much everything :)
Sam HobbsPosted Oct 27, 2010, 4:26 PM
JurePosted Oct 27, 2010, 3:20 PM
But, mine has advantage when it comes to multiple dimensions:
Dictionary:
Dictionary
test[10] = new Dictionary
test[10]["blah"] = 3;
DreamList:
DreamList
list2D[10]["blah"] = 3; // new DreamList
Sam HobbsPosted Oct 27, 2010, 2:27 PM
JurePosted Oct 27, 2010, 1:10 PM
It's even possible to use multi-dimensional DreamList:
my_list["cat"][3.14][some_object] = "value";
This is the single line you need, nothing more. Notice that index can be of any type too, not just int.
Sivaraman DhamodaranPosted Oct 27, 2010, 4:15 AM
Sam HobbsPosted Oct 26, 2010, 6:58 PM
First note that use of indexes such as in "list's elements by index" is actually using the Item method. I can't find that stated explicitly in the documentation but I am nearly certain it is so. The frustrating thing is that I don't see any documentation of "operator []" in collections. I assume that "list's elements by index" is the same as the "operator []".
The Add method is totally different from the "operator []". The Add method adds to the list. The "operator []" gets an item in the list. Some collections will work the way you want them to and add items that don't exist for a key but most collections that have a one-for-one correspondence of index number and item do not add items when the index does not exist, for the reason that Jure explained. When a collection is essentially an array with an item for every index value preceding the maximum existing index, it is more productive to assume that an out-of-range index value is a mistake. Once you accept that, you will discover it is easy to use collections that work like arrays.
Note that if you use an array such as the one that is in the C# language, you can't add new entries simply by using an out-of-range index value as an index. Try to find a language that does do that; not many do, perhaps none. Do you know what a sparse matrix is? They are like arrays except there is not a one-for-one correspondence of index value and items. You can probably use the syntax you want to with sparse matrices. The C language does not support arrays in the manner you want and the vector class in C++ does not. Arrays in VB are also not dynamic in the manner you want. I think JavaScript might but it does not have true arrays; in JavaScript, the equivalent syntax is used for something that is more of a dictionary that maps keys to items.
JurePosted Oct 26, 2010, 3:48 PM
But I have a solution for you and it's called "Indexers". Check this out:
class Program
{
static void Main(string[] args)
{
Indexer
list[1000] = 3;
Console.WriteLine(list[1000]);
Indexer
listStr[1000] = "test";
Console.WriteLine(listStr[1000]);
Console.ReadKey();
}
}
class Indexer
{
private List
private List
public T this[int index]
{
set
{
int i;
if ((i = indexes.FindIndex(new Predicate
{
values[i] = value;
return;
}
else
{
indexes.Add(index);
values.Add(value);
}
}
get
{
int i;
if ((i = indexes.FindIndex(new Predicate
{
return values[i];
}
else throw new Exception("Value does not exist!");
}
}
}
This will do what you want.
William SnellPosted Oct 26, 2010, 2:57 PM
But that isn't the case, so thanks very much for your replies. I was able to get my code running without any other problems.
JurePosted Oct 26, 2010, 3:50 AM
The second example works perfectly fine, and, it's not stupid at all.
It's great that you can initialize a list by passing a standard array to the constructor, so that you can copy elements from an array to your list when you initialize the list. That's really great.
You can use this to do what you want by passing an empty array, created on the spot with "new" keyword, so that you don't have to add 10 elements but have 10 elements already in it.
What would be stupid, is that list would have a default number of elements from the start (say 20) when you just need a few. How are you going to count all the elements that you assigned? You can't use Count property, because it will return 20, so you have to resort to some less readable, probably also less efficient code. That would be kinda stupid, wouldn't it?
Sam HobbsPosted Oct 26, 2010, 1:26 AM
Wil SnellPosted Oct 25, 2010, 8:08 PM
JurePosted Oct 25, 2010, 5:59 PM
You can set initially capacity though, by calling this overloaded constructor:
... = new List
which will set your list to 10 items.
Edit: Forgot that "capacity" and "count" is something completely different.
This will work (tested it):
... = new List
William SnellPosted Oct 25, 2010, 5:29 PM
List
But this works:
List
I'm not sure why I have to add items to a generic list before I assign values to the collection by index.
JurePosted Oct 25, 2010, 4:28 PM