views:

464

answers:

5

I have a list of string values that I want add to a hashtable or other array that can be accessed by key/index but cannot implement it. I have this working how I want but its ugly

        List<string> valueList = new List<string>();
        valueList.Add("1");
        valueList.Add("2");
        valueList.Add("3");

        Hashtable p = new Hashtable();


        valueList.ForEach(delegate(string f) { p.Add(valueList.FindIndex(v => v == f), f); });

EDIT: After James reminded me that a List will return values by index I went with a List and this is what I have ended up with

valueList.ForEach(f => sequenceList.Add(int.Parse(f)));
+1  A: 

Assuming you want the strings to be the keys and the index to be the value:

Hashtable ht = new Hashtable();

for (var i = 0; i <= valueList.Count; i++)
{
    ht.Add(valueList[i], i);
}

Otherwise switch the ht.Add parameters around. However, if that is the case you would be best just to leave it as a List < string >.

James
Yup that would work, just wondered if the built in List.ForEach could do the same thing
Jon
If you want it to have ht[index] returns a string, then I would suggest you use Mitch Wheat's solution. If it is the opposite i.e. ht[string] returns index then I suggest mines.
James
A: 
List<string> list = new List<string>{"w", "y", "u", "i", "n"};

HashSet<string> hset = new HashSet<string>(list);
Mitch Wheat
+4  A: 

Even if it compiled, it wouldn't work - calling GetEnumerator().Current will always fail because it'll give you a new iterator positioned before the first item.

What do you want the key for each item to be? If it's just its position within the list, I don't see the benefit that gives you over a list (which is already indexed by int). However, you can do it like this (assuming that valueList is a List<string>:

var dictionary = valueList.Select((item, index) => new { item, index })
                          .ToDictionary(x => x.index, x => x.item);

Adding it to an existing dictionary, I'd just do:

for (int i=0; i < valueList.Count; i++)
{
    dictionary[i] = valueList[i];
}

Not everything has to be done with lambdas :)

Note that this won't have quite the same effect as using FindIndex if you have repeated values.

Jon Skeet
+1  A: 

Try this:

valueList.ForEach(x => htable.Add(valueList.FindIndex(y => y == x), x));

Although, there's really no reason not to use a for here

for (var index = 0; index < valueList.Count; index++)
{
    htable.Add(index, valueList[index]);
}

It's more lines of code, but it's more straightforward and will perform much better (findIndex is far less efficient than using the index from the for statement).

Michael Meadows
I'd go more straightforward than that - query valueList.Count directly in the for loop. The performance difference will be negligible and the code is simpler.
Jon Skeet
@Jon Skeet, Good point. I consolodtated the for loop code down to two lines.
Michael Meadows
A: 

Using ForEach for this is not efficient, as you have to use FindIndex to find out where you are. It works, but you will do a lot of extra work:

valueList.ForEach(x => htable.Add(valueList.FindIndex(y => y == x), x));

It's better to just use a regular loop, so that you get the index without having to seek through the table:

for (int i = 0; i < valueList.Count; i++) {
   htable.Add(i, valueList[i]);
}
Guffa