我有一个Person对象列表。我想转换为Dictionary,其中键是第一个和最后一个名字(连接),值是Person对象。

问题是我有一些重复的人,所以这爆炸如果我使用以下代码:

private Dictionary<string, Person> _people = new Dictionary<string, Person>();

_people = personList.ToDictionary(
    e => e.FirstandLastName,
    StringComparer.OrdinalIgnoreCase);

我知道这听起来很奇怪,但我现在真的不关心重复的名字。如果有多个名字,我只想取一个。有没有什么方法可以让上面的代码只取其中一个名字而不会重复?


当前回答

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

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

其他回答

这应该适用于lambda表达式:

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

使用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的解决方案更好,但它同样有效。

从Carra的解开始,你也可以把它写成:

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

要处理消除重复,实现一个IEqualityComparer<Person>,可以在Distinct()方法中使用,然后获取字典就很容易了。 考虑到:

class PersonComparer : IEqualityComparer<Person>
{
    public bool Equals(Person x, Person y)
    {
        return x.FirstAndLastName.Equals(y.FirstAndLastName, StringComparison.OrdinalIgnoreCase);
    }

    public int GetHashCode(Person obj)
    {
        return obj.FirstAndLastName.ToUpper().GetHashCode();
    }
}

class Person
{
    public string FirstAndLastName { get; set; }
}

拿出你的字典:

List<Person> people = new List<Person>()
{
    new Person() { FirstAndLastName = "Bob Sanders" },
    new Person() { FirstAndLastName = "Bob Sanders" },
    new Person() { FirstAndLastName = "Jane Thomas" }
};

Dictionary<string, Person> dictionary =
    people.Distinct(new PersonComparer()).ToDictionary(p => p.FirstAndLastName, p => p);

使用LINQ等效的foldLeft功能

persons.Aggregate(new Dictionary<string,Person>(StringComparer.OrdinalIgnoreCase),
  (acc, current) => { 
    acc[current.FirstAndLastName] = current; 
    return acc; 
  });