Подтвердить что ты не робот

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


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 > ?

4b9b3361

Ответ 1

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

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

Ответ 2

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

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

Ответ 3

ИЗМЕНИТЬ

Если вы действительно чувствуете, что вам нужно получить от 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>, поэтому вы не отбрасываете данные.

Ответ 4

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

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

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

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

Ответ 5

Я понимаю, что это было помечено , но Я был буквально просто, пытаясь понять, как это сделать в вчера, поэтому я подумал, что поделился бы тем, как вы это сделаете и в 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