2009-06-26 4 views
4

Как превратить этот IEnumerable<KeyValuePair<MyType, IEnumerable<OtherType>>> в новой последовательности одного и того же типа, за исключением того, я просто хочу First(), которое в значении (IEnumerable<OtherType>). Что-то вроде этого (псевдо-код):LINQ: IEnumerable <KeyValuePair <SomeType, IEnumerable <OtherType> >> Выбор

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

ответ

8

Я уверен, если вы хотите, чтобы значение в новом KeyValuePair быть перечислимы этого типа или одного элемента. Вот обе версии

IEnumerable версии

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

несчетная Версия

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

Благодаря кучу, я нуждался в первой версии. Я на самом деле пробовал это, но забыл указать типы в KeyValuePair и получал ошибку. – epitka

6

Все, что вам не хватает является типом KeyValuePair использовать. Вы можете использовать выражение версию лямбды Джаред, или если вы хотите выражение запроса синтаксиса:

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

Если вы не хотите, чтобы явно указать аргументы типа, вы можете создать свой собственный вывод вспомогательного класса и типа использования:

// 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); 
    } 
} 

, в которой указать ваш запрос становится:

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

или

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

EDIT: К сожалению, я тоже неправильно прочитал ваш вопрос. Если вы хотите, чтобы быть точно такой же тип, т.е. со значением быть перечислимы тоже просто использовать Take(1) вместо First():

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

(Не Выведение типов милые :)

+0

Я назвал свой метод «Of» «Create» вместо этого, но мне очень нравится этот подход, когда мне нужно вручную создавать KeyValuePairs ... –

0

Почему? вы хотите получить коллекцию того же типа? Когда у вас только первый элемент, вам не нужна коллекция (IEnumerable<OtherType>), но одно значение (OtherType).

Это (как один вы вывесили) должно быть правильным (вы только нужно будет добавить общие параметры для KeyValuePair)

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

Если вы действительно хотите, чтобы получить коллекцию того же типа, напишите

var toReturn = from kv in source select new KeyValuePair<SomeType, IEnumerable<OtherType>>(kv.Key, new [] { kv.Value.First() }); 

Примечание. При переносе этого элемента в общую функцию необязательно указывать аргументы типа KeyValuePair.

KeyValuePair<TKey, TValue> Pair<TKey, TValue>(TKey key, TValue value) { 
    return new KeyValuePair<TKey, TValue>(key, value); 
} 
// 
var foo = Pair(1, "Hello"); 
+0

Мне нужен был тот же тип, чтобы иметь возможность подключить его к тому же методу, который обрабатывает другой один. Это упорядочено по дате создания desc, и мне нужно показать все или только последние. – epitka

1
var toReturn = source 
.ToDictionary(
    kvp => kvp.Key, 
    kvp => kvp.Value.Take(1) 
);