3

Is there an elegant way of converting this string array:

string[] a = new[] {"name", "Fred", "colour", "green", "sport", "tennis"};

into a Dictionary such that every two successive elements of the array become one {key, value} pair of the dictionary (I mean {"name" -> "Fred", "colour" -> "green", "sport" -> "tennis"})?

I can do it easily with a loop, but is there a more elegant way, perhaps using LINQ?

4
  • Possibly a duplicate of this question. At least, the solutions will probably be virtually the same. Commented Sep 14, 2012 at 14:21
  • I fixed your syntax; it didn't compile before. Commented Sep 14, 2012 at 14:22
  • Another related question that may help you. Contains itself links to other helpful questions it was marked as a duplicate of. Commented Sep 14, 2012 at 14:32
  • Thanks to everyone who contributed answers and links to similar questions. There are some interesting and thought-provoking ideas here. My favourite answers are Turbot's and digEmAll's. Commented Sep 17, 2012 at 10:30

7 Answers 7

5
var dict = a.Select((s, i) => new { s, i })
            .GroupBy(x => x.i / 2)
            .ToDictionary(g => g.First().s, g => g.Last().s);
Sign up to request clarification or add additional context in comments.

Comments

4

Since it's an array I would do this:

var result = Enumerable.Range(0,a.Length/2)
                       .ToDictionary(x => a[2 * x], x => a[2 * x + 1]);

Comments

2

How about this ?

    var q = a.Zip(a.Skip(1), (Key, Value) => new { Key, Value })
             .Where((pair,index) => index % 2 == 0)
             .ToDictionary(pair => pair.Key, pair => pair.Value);

1 Comment

This is going through the list twice. That would be a problem for IEnumerable (I know question was about array) also, it is doing extra work.
1

I've made a simular method to handle this type of request. But since your array contains both keys and values i think you need to split this first.

Then you can use something like this to combine them

public static IDictionary<T, T2> ZipMyTwoListToDictionary<T, T2>(IEnumerable<T> listContainingKeys, IEnumerable<T2> listContainingValue)
    {
        return listContainingValue.Zip(listContainingKeys, (value, key) => new { value, key }).ToDictionary(i => i.key, i => i.value);
    }

3 Comments

Some suggestions: the name is misleading, call it ZipToDictionary (there are no lists involved). And use descriptive type elements, i.e. TKey, TValue
So how do you get from the array to the two enumerables?
I just added this answer which uses this general idea, but expands on it to solve the problem I previously mentioned.
0
a.Select((input, index) = >new {index})
  .Where(x=>x.index%2!=0)
  .ToDictionary(x => a[x.index], x => a[x.index+1])

I would recommend using a for loop but I have answered as requested by you.. This is by no means neater/cleaner..

Comments

0
public static IEnumerable<T> EveryOther<T>(this IEnumerable<T> source)
{
    bool shouldReturn = true;
    foreach (T item in source)
    {
        if (shouldReturn)
            yield return item;
        shouldReturn = !shouldReturn;
    }
}

public static Dictionary<T, T> MakeDictionary<T>(IEnumerable<T> source)
{
    return source.EveryOther()
        .Zip(source.Skip(1).EveryOther(), (a, b) => new { Key = a, Value = b })
        .ToDictionary(pair => pair.Key, pair => pair.Value);
}

The way this is set up, and because of the way Zip works, if there are an odd number of items in the list the last item will be ignored, rather than generation some sort of exception.

Note: derived from this answer.

Comments

0
IEnumerable<string> strArray = new string[] { "name", "Fred", "colour", "green", "sport", "tennis" };


            var even = strArray.ToList().Where((c, i) => (i % 2 == 0)).ToList();
            var odd = strArray.ToList().Where((c, i) => (i % 2 != 0)).ToList();

            Dictionary<string, string> dict = even.ToDictionary(x => x, x => odd[even.IndexOf(x)]);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.