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?

Adam
  • 15,537
  • 2
  • 42
  • 63
Klitos Kyriacou
  • 10,634
  • 2
  • 38
  • 70
  • Possibly a duplicate of [this question](http://stackoverflow.com/questions/4123685/how-to-get-alternate-elements-using-enumerable-in-c-sharp). At least, the solutions will probably be virtually the same. – O. R. Mapper Sep 14 '12 at 14:21
  • I fixed your syntax; it didn't compile before. – Adam Sep 14 '12 at 14:22
  • Another [related question](http://stackoverflow.com/questions/11269847/select-even-odd-elements-in-ienumerablet) that may help you. Contains itself links to other helpful questions it was marked as a duplicate of. – O. R. Mapper Sep 14 '12 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. – Klitos Kyriacou Sep 17 '12 at 10:30

7 Answers7

5
var dict = a.Select((s, i) => new { s, i })
            .GroupBy(x => x.i / 2)
            .ToDictionary(g => g.First().s, g => g.Last().s);
L.B
  • 114,136
  • 19
  • 178
  • 224
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]);
digEmAll
  • 56,430
  • 9
  • 115
  • 140
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);
Turbot
  • 5,095
  • 1
  • 22
  • 30
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);
    }
Jonas W
  • 3,200
  • 1
  • 31
  • 44
  • Some suggestions: the name is misleading, call it `ZipToDictionary` (there are no lists involved). And use descriptive type elements, i.e. `TKey, TValue` – Adam Sep 14 '12 at 14:20
  • 1
    So how do you get from the array to the two enumerables? – Servy Sep 14 '12 at 14:20
  • I just added [this answer](http://stackoverflow.com/a/12426649/1159478) which uses this general idea, but expands on it to solve the problem I previously mentioned. – Servy Sep 14 '12 at 14:35
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..

Baz1nga
  • 15,485
  • 3
  • 35
  • 61
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.

Community
  • 1
  • 1
Servy
  • 202,030
  • 26
  • 332
  • 449
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)]);
Dhanasekar Murugesan
  • 3,141
  • 1
  • 18
  • 21