0

I am using Dictionary class as follows

Dictionary<string, string> dict = new Dictionary<string, string>()
{
   {"1", "One"} 
   {"2", "Two"}
   {"3", "three"}
   {"4", "four"}
};

Now I am trying to get the value of each of the keys and pass them as parameter to a function. Something like :

myFunction(<get the first key and pass its value as parameter>);
myFunction(<get the second key and pass its value as parameter>);
myFunction(<get the third key and pass its value as parameter>);
myFunction(<get the fourth key and pass its value as parameter>);

So these are four calls to the function.

I cannot use a for loop here obviously because if I do so, say for example I start the loop from 1, then the value for the first run of the loop will be 1 and it will pick up the first key throughout these four calls of the function which I do not want. I want to get 1 in the first call of the functions, get second value in the second call and so on.

I am not able to figure out a way to do this. Any suggestions would be of great help.

abc abc
  • 3
  • 2
  • 3

5 Answers5

5

The same key for four calls?

Or how not to do loops.

I cannot use a for loop here obviously because if I do so, say for example I start the loop from 1, then the value for the first run of the loop will be 1 and it will pick up the first key throughout these four calls of the function which I do not want. I want to get 1 in the first call of the functions, get second value in the second call and so on.

Don't put the four calls in the loop.

If you do either this:

var keys = new List<string>(dict.Keys);
for (var index = 0; index < keys.Count; index++)
{
    myFunction(dict[keys[index]]);
    myFunction(dict[keys[index]]);
    myFunction(dict[keys[index]]);
    myFunction(dict[keys[index]]);
}

Or this:

var values = new List<string>(dict.Values);
for (var index = 0; index < values.Count; index++)
{
    myFunction(values[index]);
    myFunction(values[index]);
    myFunction(values[index]);
    myFunction(values[index]);
}

Or this:

foreach (var key in dict.Keys)
{
    myFunction(dict[key]);
    myFunction(dict[key]);
    myFunction(dict[key]);
    myFunction(dict[key]);
}

Or this:

foreach (var pair in dict)
{
    myFunction(pair.Value);
    myFunction(pair.Value);
    myFunction(pair.Value);
    myFunction(pair.Value);
}

Or this:

foreach (var value in dict.Values)
{
    myFunction(value);
    myFunction(value);
    myFunction(value);
    myFunction(value);
}

You will get hte function myFunction being called with the same value four times, for each value.


How to do for or foreach loops

Instead, put a single call in the loop. Remember that the loop is used to repeat something, so by placing it in the loop it will be repeated.

So do this:

var keys = new List<string>(dict.Keys);
for (var index = 0; index < keys.Count; index++)
{
    myFunction(dict[keys[index]]);
}

So do this:

var values = new List<string>(dict.Values);
for (var index = 0; index < values.Count; index++)
{
    myFunction(values[index]);
}

Or this:

foreach (var key in dict.Keys)
{
    myFunction(dict[key]);
}

Or this:

foreach (var pair in dict)
{
    myFunction(pair.Value);
}

Or this:

foreach (var value in dict.Values)
{
    myFunction(value);
}

You may also do this:

var keys = new List<string>(dict.Keys);
keys.ForEach(key => myFunction(dict[key]));

Or this:

var values = new List<string>(dict.Values);
values.ForEach(value => myFunction(value));

Or if you prefer to throw some Linq in the mix (which I presume, since you added the Linq tag), you can do this:

dict.Keys.ToList().ForEach(key => myFunction(dict[key]));

This also works:

dict.Values.ToList().ForEach(value => myFunction(value));

How to do while loops

Let's say that you don't want to do a for or foreach loop at all. Well, lets see...

A for loop like this one:

var keys = new List<string>(dict.Keys);
for (var index = 0; index < keys.Count; index++)
{
    myFunction(dict[keys[index]]);
}

Can be done like this:

var keys = new List<string>(dict.Keys);
var index = 0;
while (index < keys.Count)
{
    myFunction(dict[keys[index]]);
    index++
}

And a foreach loop like this one:

foreach (var key in dict.Keys)
{
    myFunction(dict[key]);
}

Can be done like this:

var enumerator = dict.Keys.GetEnumerator();
try
{
    while (enumerator.MoveNext())
    {
        var key = enumerator.Current;
        myFunction(dict[key]);
    }
}
finally
{
    enumerator.Dispose();
}

Of course, you can also do it like this:

var enumerator = dict.Values.GetEnumerator();
try
{
    while (enumerator.MoveNext())
    {
        var value = enumerator.Current;
        myFunction(value);
    }
}
finally
{
    enumerator.Dispose();
}

Or like this:

var enumerator = dict.GetEnumerator();
try
{
    while (enumerator.MoveNext())
    {
        var pair = enumerator.Current;
        myFunction(pair.Value);
    }
}
finally
{
    enumerator.Dispose();
}

This transformation is similar to the one the compiler does internally. By doing this, you may have more flexibility in some situations... yet, it is also more error prone.


How to not do loop

Let's pretend that you don't want to loop at all. This is possible if you know at compile time what is the number of elements. We can get there by unrolling a for, such as the while we had before:

var keys = new List<string>(dict.Keys);
var index = 0;
while (index < keys.Count)
{
    myFunction(dict[keys[index]]);
    index++
}

Turn the while into an if and repeat it. The result looks like this:

var keys = new List<string>(dict.Keys);
var index = 0;
if (index < keys.Count)
{
    myFunction(dict[keys[index]]);
    index++
}
if (index < keys.Count)
{
    myFunction(dict[keys[index]]);
    index++
}
if (index < keys.Count)
{
    myFunction(dict[keys[index]]);
    index++
}
if (index < keys.Count)
{
    myFunction(dict[keys[index]]);
    index++
}

Well, if know the value of index and the number of items in the dictionary, we know when index < keys.Count is true. So we can remove those if statements and repelace them with their inner code (since they are true). We end up with this:

var keys = new List<string>(dict.Keys);
var index = 0;
myFunction(dict[keys[index]]);
index = 1;
myFunction(dict[keys[index]]);
index = 2;
myFunction(dict[keys[index]]);
index = 3;
myFunction(dict[keys[index]]);
index = 4;

Finally, we inline the index variable:

var keys = new List<string>(dict.Keys);
myFunction(dict[keys[0]]);
myFunction(dict[keys[1]]);
myFunction(dict[keys[2]]);
myFunction(dict[keys[3]]);

Ta-Da! no loop.

Of course, you can also do it like this:

var values = new List<string>(dict.Values);
myFunction(values[0]);
myFunction(values[1]);
myFunction(values[2]);
myFunction(values[3]);
Theraot
  • 31,890
  • 5
  • 57
  • 86
1

What you really have to know that a dictionary is not ordered. Saying that you want the "first" key just does not make sense. Sure you can convert the KeyCollection you got from the Keys property of the dictionary into a List<string> but that can result in any arbitrary different order.

If by the "first" key you mean the key "1", and by the "second" key you mean the key "2" and so on, then I think a List<string> is a better fit for this. It is ordered and you can use numbers to access the elements.

Also, I don't get it why for loops won't work. Try this:

for (int i = 1 ; i <= 4 ; i++) {
    myFunction(dict[i.toString()]);
}

This will pass values in the order of "One" -> "Two" -> "three" -> "four".

Sweeper
  • 213,210
  • 22
  • 193
  • 313
0

You can get the keys using this code,

List<string> keyList = new List<string>(dict.Keys);

and then pass to the function with the index,

 myFunction(keyList[0]);
Sajeetharan
  • 216,225
  • 63
  • 350
  • 396
  • ah, this worked, exactly what I wanted, thanks a ton mate :) – abc abc May 13 '17 at 08:27
  • 2
    I'd argue that there's no reason whatsoever to create a new `List` just to contain the keys when `dict.Keys` is a perfectly accessible collection by itself. Furthermore, doing this disconnects the list of keys from the dictionary, so if anything gets added/removed, the list won't know about it. – Abion47 May 13 '17 at 10:28
0

Why can't you use loops? A foreach would do you just fine:

foreach (string key in dict.Keys)
{
    myFunction(dict[key]);
}
Abion47
  • 22,211
  • 4
  • 65
  • 88
0
foreach(var item in dict)
{
  myFunction(item.Value);
}

OR

foreach(var dictValue in dict.Values)
{
  myFunction(dictValue);
}

Not sure why you think loop wont work here