如何编写导致字典的LINQ查询?

时间:2012-12-19 09:50:51

标签: c# .net linq collections dictionary


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

如何获取字典&lt; string,string&gt;?

6 个答案:

答案 0 :(得分:42)

您需要指定Dictionary

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

答案 1 :(得分:12)

字典不能包含多个相等的键,因此您应该确保(或知道)不是这种情况。您可以使用GroupBy来确保它:

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

答案 2 :(得分:8)

修改

如果您确实需要隐式地从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>,因此您不会丢弃数据。

答案 3 :(得分:5)

尝试将NickName作为键,将名称作为值

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

但请注意,字典不允许重复,因此上面会为具有相同昵称的重复记录引发错误。也许你想使用类似于Dictionary的Lookup,但允许重复

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

答案 4 :(得分:0)

我意识到这是用标记的,但我确实只是试图弄明白昨天如何在中做到这一点,所以我想我会分享你如何在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

答案 5 :(得分:0)

您也可以通过投射来获取LINQ查询中的词典:

var d2 = (Dictionary<string, string>)q;

这适用于Visual Studio 2013。