我想在词典中找到一个键,如果找到了替换值,或者如果不是则添加键/值。
代码:
Owner Inventory
--------- --------------
Noemi 3 Owner1:Noemi | Owner2:Noemi
Carl 3 Owner1:Carl | Owner2:Carl
Darla 2 Owner1:Darla| Owner2:null
Paola 2 Owner1:null| Owner2:Paola
LINQ解决方案(抛出public class MyObject
{
public string UniqueKey { get; set; }
public string Field1 { get; set; }
public string Field2 { get; set; }
}
):
An item with the same key has already been added.
ForEach解决方案(有效):
Dictionary<string, MyObject> objectDict = csvEntries.ToDictionary(csvEntry => csvEntry.ToMyObject().UniqueKey, csvEntry => csvEntry.ToMyObject());
我真的很喜欢LINQ解决方案,但就其而言,它会引发上述错误。有没有什么好方法可以避免错误并使用LINQ?
答案 0 :(得分:14)
您可以使用GroupBy
创建唯一键:
Dictionary<string, MyObject> objectDict = csvEntries
.Select(csvEntry => csvEntry.ToMyObject())
.GroupBy(x => x.UniqueKey)
.ToDictionary(grp => grp.Key, grp => grp.First());
但是,您可以使用grp.First()
或ToList
创建一个集合,而不是ToArray
。在这种情况下,如果密钥重复,则不会使用任意对象。
另一种选择是使用Lookup<TKey, TValue>
允许重复键甚至是不存在的键,在这种情况下你得到一个空序列。
var uniqueKeyLookup = csvEntries
.Select(csvEntry => csvEntry.ToMyObject())
.ToLookup(x => x.UniqueKey);
IEnumerable<MyObject> objectsFor1234 = uniqueKeyLookup["1234"]; // empty if it doesn't exist
答案 1 :(得分:1)
基于Rango的答案,这是您可以使用的扩展方法,因此您无需在整个项目中重复实现:
NOTICE: found : f NOTICE: payment_method (,,,,,,,,,,,,)
默认情况下,当有重复项时,它将选择第一个元素,但是我提供了一个可选参数,您可以在其中指定备用选择器。调用扩展方法的示例:
public static class DictionaryExtensions
{
public static Dictionary<TKey, TValue> ToDictionaryWithDupSelector<TKey, TValue>(
this IEnumerable<TValue> enumerable,
Func<TValue, TKey> groupBy, Func<IEnumerable<TValue>, TValue> selector = null) {
if (selector == null)
selector = new Func<IEnumerable<TValue>, TValue>(grp => grp.First());
return enumerable
.GroupBy(e => groupBy(e))
.ToDictionary(grp => grp.Key, grp => selector(grp));
}
}