标题已经够基础了,为什么我不能:
Dictionary<string, string> dic = new Dictionary<string, string>();
dic.AddRange(MethodThatReturnAnotherDic());发布于 2011-05-19 04:29:58
对原始问题的评论很好地总结了这一点:
,因为从来没有人设计、指定、实现、测试、记录和发布该功能。- @Gabe Moothart
至于为什么呢?嗯,可能是因为合并字典的行为不能以一种符合框架指导方针的方式进行推理。
AddRange不存在,因为范围对于关联容器没有任何意义,因为数据范围允许重复条目。例如,如果你有一个IEnumerable<KeyValuePair<K,T>>,那么这个集合就不能防止重复的条目。
添加一组键-值对,甚至合并两个字典的行为都很简单。然而,如何处理多个重复条目的行为却并非如此。
在处理重复项时,该方法的行为应该是什么?
我能想到的解决方案至少有三种:
对于作为重复项的第一个条目,
当抛出异常时,原始字典的状态应该是什么?
Add几乎总是作为原子操作实现:它成功并更新集合的状态,或者失败,而集合的状态保持不变。由于AddRange可能会由于重复错误而失败,因此保持其行为与Add一致的方法也是通过在任何重复项上抛出异常来使其原子化,并使原始字典的状态保持不变。
作为API使用者,必须迭代地删除重复的元素将是单调乏味的,这意味着AddRange应该抛出一个包含所有重复值的异常。
然后,选择归结为:
对于所有重复项,
有支持这两种用例的论据。为此,您是否向签名添加了IgnoreDuplicates标志?
IgnoreDuplicates标志(当设置为true时)也将提供显著的速度,因为底层实现将绕过重复检查的代码。
所以现在,您有了一个标志,它允许AddRange支持这两种情况,但有一个未记录的副作用(这是框架设计者非常努力避免的)。
摘要
由于在处理重复项时没有明确、一致和预期的行为,因此更容易不一起处理它们,也不提供一开始就提供的方法。
如果您发现自己必须不断地合并字典,那么您当然可以编写自己的扩展方法来合并字典,这将以适用于您的应用程序的方式运行。
发布于 2015-03-09 20:38:05
我有一些解决方案:
Dictionary<string, string> mainDic = new Dictionary<string, string>() {
{ "Key1", "Value1" },
{ "Key2", "Value2.1" },
};
Dictionary<string, string> additionalDic= new Dictionary<string, string>() {
{ "Key2", "Value2.2" },
{ "Key3", "Value3" },
};
mainDic.AddRangeOverride(additionalDic); // Overrides all existing keys
// or
mainDic.AddRangeNewOnly(additionalDic); // Adds new keys only
// or
mainDic.AddRange(additionalDic); // Throws an error if keys already exist
// or
if (!mainDic.ContainsKeys(additionalDic.Keys)) // Checks if keys don't exist
{
mainDic.AddRange(additionalDic);
}..。
namespace MyProject.Helper
{
public static class CollectionHelper
{
public static void AddRangeOverride<TKey, TValue>(this IDictionary<TKey, TValue> dic, IDictionary<TKey, TValue> dicToAdd)
{
dicToAdd.ForEach(x => dic[x.Key] = x.Value);
}
public static void AddRangeNewOnly<TKey, TValue>(this IDictionary<TKey, TValue> dic, IDictionary<TKey, TValue> dicToAdd)
{
dicToAdd.ForEach(x => { if (!dic.ContainsKey(x.Key)) dic.Add(x.Key, x.Value); });
}
public static void AddRange<TKey, TValue>(this IDictionary<TKey, TValue> dic, IDictionary<TKey, TValue> dicToAdd)
{
dicToAdd.ForEach(x => dic.Add(x.Key, x.Value));
}
public static bool ContainsKeys<TKey, TValue>(this IDictionary<TKey, TValue> dic, IEnumerable<TKey> keys)
{
bool result = false;
keys.ForEachOrBreak((x) => { result = dic.ContainsKey(x); return result; });
return result;
}
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{
foreach (var item in source)
action(item);
}
public static void ForEachOrBreak<T>(this IEnumerable<T> source, Func<T, bool> func)
{
foreach (var item in source)
{
bool result = func(item);
if (result) break;
}
}
}
}玩得开心。
发布于 2016-06-29 00:37:31
如果有人像我一样遇到这个问题-可以通过使用IEnumerable扩展方法来实现"AddRange“:
var combined =
dict1.Union(dict2)
.GroupBy(kvp => kvp.Key)
.Select(grp => grp.First())
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);组合字典的主要技巧是处理重复的键。在上面的代码中,它是部分.Select(grp => grp.First())。在这种情况下,它只是从复制组中获取第一个元素,但如果需要,您可以在那里实现更复杂的逻辑。
https://stackoverflow.com/questions/6050633
复制相似问题