Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LINQ: IEnumerable<KeyValuePair<SomeType, IEnumerable<OtherType>>> selection

Tags:

linq

How do I transform this IEnumerable<KeyValuePair<MyType, IEnumerable<OtherType>>> into new sequence of the same type, except I just want First() that is in the value (IEnumerable<OtherType>). Something like this (pseudo code):

  var toReturn = from kv in source
                 let k = new KeyValuePair(kv.Key, kv.Value.First())
                 select k;
like image 352
epitka Avatar asked Jun 26 '09 14:06

epitka


2 Answers

I'm unsure if you want the Value in the new KeyValuePair to be an enumerable of that type or a single element. Here's both versions

IEnumerable version

var toReturn = source.Select(x => new KeyValuePair<SomeType,IEnumerable<SomeOtherType>>(x.Key, x.Value.Take(1));

Non-Enumerable Version

var toReturn = source.Select(x => new KeyValuePair<SomeType,SomeOtherType>(x.Key,x.Value.First());
like image 153
JaredPar Avatar answered Sep 28 '22 18:09

JaredPar


All you're missing is the type of KeyValuePair to use. You could use Jared's lambda expression version, or if you like the query expression syntax:

var toReturn = from kv in source
               select new KeyValuePair<MyType, OtherType>(kv.Key, 
                                                          kv.Value.First());

If you don't want to explicitly specify the type arguments, you could create your own helper class and use type inference:

// Non-generic helper class.
public static class KeyValuePair
{
    public static KeyValuePair<TKey, TValue> Of(TKey key, TValue value)
    {
        return new KeyValuePair<TKey, TValue>(key, value); 
    }
}

at which point your query becomes:

var toReturn = from kv in source
               select KeyValuePair.Of(kv.Key, kv.Value.First());

or

var toReturn = source.Select(kv => KeyValuePair.Of(kv.Key, kv.Value.First());

EDIT: Oops - I think I'd misread your question as well. If you want it to be of the exact same type, i.e. with the value being enumerable too, just use Take(1) instead of First():

var toReturn = source.Select(kv => KeyValuePair.Of(kv.Key, kv.Value.Take(1));

(Isn't type inference lovely? :)

like image 43
Jon Skeet Avatar answered Sep 28 '22 19:09

Jon Skeet