leo*_*ora 145 c# linq dictionary
我有一个Person对象列表.我想转换为一个字典,其中键是名字和姓氏(连接),值是Person对象.
问题是我有一些重复的人,所以如果我使用这个代码会爆炸:
private Dictionary<string, Person> _people = new Dictionary<string, Person>();
_people = personList.ToDictionary(
e => e.FirstandLastName,
StringComparer.OrdinalIgnoreCase);
Run Code Online (Sandbox Code Playgroud)
我知道这听起来很奇怪,但我现在并不关心重复的名字.如果有多个名字我只想抓一个.无论如何,我可以在上面写这个代码,所以它只需要一个名字,并没有炸毁重复?
Luk*_*keH 392
LINQ解决方案:
// Use the first value in group
var _people = personList
.GroupBy(p => p.FirstandLastName, StringComparer.OrdinalIgnoreCase)
.ToDictionary(g => g.Key, g => g.First(), StringComparer.OrdinalIgnoreCase);
// Use the last value in group
var _people = personList
.GroupBy(p => p.FirstandLastName, StringComparer.OrdinalIgnoreCase)
.ToDictionary(g => g.Key, g => g.Last(), StringComparer.OrdinalIgnoreCase);
Run Code Online (Sandbox Code Playgroud)
如果您更喜欢非LINQ解决方案,那么您可以执行以下操作:
// Use the first value in list
var _people = new Dictionary<string, Person>(StringComparer.OrdinalIgnoreCase);
foreach (var p in personList)
{
if (!_people.ContainsKey(p.FirstandLastName))
_people[p.FirstandLastName] = p;
}
// Use the last value in list
var _people = new Dictionary<string, Person>(StringComparer.OrdinalIgnoreCase);
foreach (var p in personList)
{
_people[p.FirstandLastName] = p;
}
Run Code Online (Sandbox Code Playgroud)
Car*_*rra 66
这是明显的非linq解决方案:
foreach(var person in personList)
{
if(!myDictionary.Keys.Contains(person.FirstAndLastName))
myDictionary.Add(person.FirstAndLastName, person);
}
Run Code Online (Sandbox Code Playgroud)
Til*_*ito 38
使用Distinct()并且没有分组的Linq解决方案是:
var _people = personList
.Select(item => new { Key = item.Key, FirstAndLastName = item.FirstAndLastName })
.Distinct()
.ToDictionary(item => item.Key, item => item.FirstFirstAndLastName, StringComparer.OrdinalIgnoreCase);
Run Code Online (Sandbox Code Playgroud)
我不知道它是否比LukeH的解决方案更好,但它也可以.
Ank*_*ass 29
这应该适用于lambda表达式:
personList.Distinct().ToDictionary(i => i.FirstandLastName, i => i);
Run Code Online (Sandbox Code Playgroud)
pal*_*wim 11
您还可以使用ToLookupLINQ函数,然后您可以将它与字典几乎互换使用.
_people = personList
.ToLookup(e => e.FirstandLastName, StringComparer.OrdinalIgnoreCase);
_people.ToDictionary(kl => kl.Key, kl => kl.First()); // Potentially unnecessary
Run Code Online (Sandbox Code Playgroud)
这将基本上在LukeH的答案中进行GroupBy ,但是会给出Dictionary提供的散列.因此,您可能不需要将其转换为Dictionary,而只需First在需要访问键的值时使用LINQ 函数.
要处理消除重复项,请实现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; }
}
Run Code Online (Sandbox Code Playgroud)
获取你的字典:
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);
Run Code Online (Sandbox Code Playgroud)
您可以创建类似于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;
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,如果有重复项,则最后一个值获胜.