时间:2010-07-23 14:20:07

标签: c# linq dictionary

11 个答案:

答案 0 :(得分:373)

答案 1 :(得分:57)

答案 2 :(得分:37)

使用Distinct()并且没有分组的Linq解决方案是:

var _people = personList
    .Select(item => new { Key = item.Key, FirstAndLastName = item.FirstAndLastName })
    .Distinct()
    .ToDictionary(item => item.Key, item => item.FirstFirstAndLastName, StringComparer.OrdinalIgnoreCase);

我不知道它是否比LukeH的解决方案更好,但它也有效。

答案 3 :(得分:26)

这应该适用于lambda表达式:

personList.Distinct().ToDictionary(i => i.FirstandLastName, i => i);

答案 4 :(得分:10)

您还可以使用ToLookup LINQ函数,然后您可以将其与字典几乎互换使用。

_people = personList
    .ToLookup(e => e.FirstandLastName, StringComparer.OrdinalIgnoreCase);
_people.ToDictionary(kl => kl.Key, kl => kl.First()); // Potentially unnecessary

这基本上会在LukeH's answer中执行GroupBy,但会提供Dictionary提供的散列。因此,您可能不需要将其转换为Dictionary,但只要您需要访问密钥的值,就可以使用LINQ First函数。

答案 5 :(得分:7)

答案 6 :(得分:5)

您可以创建类似于ToDictionary()的扩展方法,区别在于它允许重复。类似的东西:

    public static Dictionary<TKey, TElement> SafeToDictionary<TSource, TKey, TElement>(
        this IEnumerable<TSource> source, 
        Func<TSource, TKey> keySelector, 
        Func<TSource, TElement> elementSelector, 
        IEqualityComparer<TKey> comparer = null)
    {
        var dictionary = new Dictionary<TKey, TElement>(comparer);

        if (source == null)
        {
            return dictionary;
        }

        foreach (TSource element in source)
        {
            dictionary[keySelector(element)] = elementSelector(element);
        }

        return dictionary; 
    }

在这种情况下,如果有重复项,则最后一个值获胜。

答案 7 :(得分:2)

        DataTable DT = new DataTable();
        DT.Columns.Add("first", typeof(string));
        DT.Columns.Add("second", typeof(string));

        DT.Rows.Add("ss", "test1");
        DT.Rows.Add("sss", "test2");
        DT.Rows.Add("sys", "test3");
        DT.Rows.Add("ss", "test4");
        DT.Rows.Add("ss", "test5");
        DT.Rows.Add("sts", "test6");

        var dr = DT.AsEnumerable().GroupBy(S => S.Field<string>("first")).Select(S => S.First()).
            Select(S => new KeyValuePair<string, string>(S.Field<string>("first"), S.Field<string>("second"))).
           ToDictionary(S => S.Key, T => T.Value);

        foreach (var item in dr)
        {
            Console.WriteLine(item.Key + "-" + item.Value);
        }

答案 8 :(得分:1)

如果我们希望返回词典中的所有Person(而不是只有一个Person),我们可以:

var _people = personList
.GroupBy(p => p.FirstandLastName)
.ToDictionary(g => g.Key, g => g.Select(x=>x));

答案 9 :(得分:1)

大多数其他答案的问题是它们使用DistinctGroupByToLookup,从而在幕后创建了一个额外的Dictionary。同样,ToUpper创建额外的字符串。 这就是我所做的,除了一个更改外,它几乎是Microsoft代码的完全相同的副本:

    public static Dictionary<TKey, TSource> ToDictionaryIgnoreDup<TSource, TKey>
        (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer = null) =>
        source.ToDictionaryIgnoreDup(keySelector, i => i, comparer);

    public static Dictionary<TKey, TElement> ToDictionaryIgnoreDup<TSource, TKey, TElement>
        (this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, IEqualityComparer<TKey> comparer = null)
    {
        if (keySelector == null)
            throw new ArgumentNullException(nameof(keySelector));
        if (elementSelector == null)
            throw new ArgumentNullException(nameof(elementSelector));
        var d = new Dictionary<TKey, TElement>(comparer ?? EqualityComparer<TKey>.Default);
        foreach (var element in source)
            d[keySelector(element)] = elementSelector(element);
        return d;
    }

因为在索引器上进行设置会导致它添加密钥,所以不会抛出该密钥,并且只会执行一次密钥查找。您也可以给它一个IEqualityComparer,例如StringComparer.OrdinalIgnoreCase

答案 10 :(得分:0)

从Carra的解决方案开始,您也可以将其编写为:

foreach(var person in personList.Where(el => !myDictionary.ContainsKey(el.FirstAndLastName)))
{
    myDictionary.Add(person.FirstAndLastName, person);
}