Как написать запрос LINQ, в результате чего появился словарь?

294
33


public class Person
{
public string NickName{ get; set; }
public string Name{ get; set; }
}

var pl = new List<Person>;

var q = from p in pl
where p.Name.First() == 'A'
orderby p.NickName
select new KeyValuePair<String, String>(p.NickName, p.Name);

var d1 = q.ToList(); // Gives List<KeyValuePair<string, string>>
var d2 = q.ToDictionary(); // Does not compile


Как получить словарь < string, string > ?

спросил(а) 2021-01-19T17:45:40+03:00 9 месяцев, 1 неделя назад
1
Решение
291

Вам нужно указать значения для Dictionary

var d2 = q.ToDictionary(p => p.NickName, p => p.Name);

ответил(а) 2021-01-19T17:45:40+03:00 9 месяцев, 1 неделя назад
164

Словарь не может содержать несколько одинаковых ключей, поэтому вы должны убедиться (или знать), что это не так. Вы можете использовать GroupBy, чтобы убедиться в этом:

Dictionary<string, string> dict = pl
.Where(p => p.Name.First() == 'A')
.GroupBy(p => p.NickName)
.ToDictionary(g => g.Key, g => g.First().Name);

ответил(а) 2021-01-19T17:45:40+03:00 9 месяцев, 1 неделя назад
137

ИЗМЕНИТЬ


Если вы действительно чувствуете, что вам нужно получить от IEnumerable<KeyValuePair<TKey, TValue>> до Dictionary неявно, вы можете добавить это расширение.


public static IDictionary<TKey, ToValue> ToDictionary<TKey, TValue>(
this IEnumerable<KeyValuePair<TKey, TValue>> source)
{
return source.ToDictionary(p => p.Key, p => p.Value);
}

Затем вы можете вызвать ToDictionary() на любом IEnumerable<KeyValuePair<TKey, TValue>>.


РЕДАКТИРОВАТЬ 2


Если вы ожидаете дублирования, вы также можете создать расширение ToLookup().


public static ILookup<TKey, TValue> ToLookup<TKey, TValue>(
this IEnumerable<KeyValuePair<TKey, TValue>> source)
{
return source.ToLookup(p => p.Key, p => p.Value);
}

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


public static IDictionary<TKey, ToValue> ToDictionary<TKey, TValue>(
this IEnumerable<KeyValuePair<TKey, TValue>> source,
Func<<IEnumerable<TValue>, TValue> selector)
{
return source
.Lookup(p => p.Key, p => p.Value);
.ToDictionary(l => l.Key, l => selector(l));
}

Если вы произвольно отбросьте все, кроме "первого" (что означает это без элемента OrderBy), вы можете использовать это расширение следующим образом:


pairs.ToDictionary(v => v.First()); 

В целом вы можете удалить большую часть своего кода и сделать,


var q = from p in pl
where p.Name.First() == 'A';
var d = q.ToDictionary(p => p.NickName, p => p.Name);

Если могут быть дубликаты, do


var d = q.ToLookup(p => p.NickName, p => p.Name);

но заметьте, это возвращает ILookup<TKey, TElement>, Item указатель которого возвращает IEnumerable<TElement>, поэтому вы не отбрасываете данные.

ответил(а) 2021-01-19T17:45:40+03:00 9 месяцев, 1 неделя назад
112

Попробуйте использовать NickName в качестве ключа и имя как значение


var d2 = q.ToDictionary (p => p.NickName, p=>p.Name);

Но обратите внимание, что словарь не позволяет дублировать, поэтому выше будет вызывать ошибку для дубликатов записей с одним и тем же псевдонимом. Возможно, вы хотели бы использовать Lookup, который похож на словарь, но позволяет дублировать


var d2 = q.ToLookup (p => p.NickName, p=>p.Name);

ответил(а) 2021-01-19T17:45:40+03:00 9 месяцев, 1 неделя назад
46

Я понимаю, что это было помечено С#, но Я был буквально просто, пытаясь понять, как это сделать в vb.net вчера, поэтому я подумал, что поделился бы тем, как вы это сделаете и в VB:


Public Class Person
Property NickName As String
Property Name As String
End Class

Sub Main()
Dim p1 As New List(Of Person)

'*** Fill the list here ***

Dim q = (From p In p1
Where p.Name.First = "A"
Select p.NickName, p.Name).ToDictionary(
Function(k) k.NickName,
Function(v) v.Name)
End Sub

ответил(а) 2021-01-19T17:45:40+03:00 9 месяцев, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема