我有一个由一些较大的配置文件填充的项目列表。
List<TextEntrtry> localTextEntries;
包含TextEntry类型的元素:
public class TextEntry
{
public Guid Id { get; set; }
....
此列表将转换为字典:
Dictionary<Guid, TextEntry> textEntries;
此行抛出异常&#39;具有相同键的元素已存在&#39;:
textEntries = localTextEntries.ToDictionary(x => x.Id);
显然我的列表包含两个具有相同Id的元素。
我的问题:找出导致异常的元素的最佳方法是什么?
(这将允许我生成有意义的错误消息)
答案 0 :(得分:2)
在您的收藏集上运行此选项以获取具有重复条目的收件人:
var duplicateEntries = localTextEntries.GroupBy(k = > k.Id)
.Where(g = > g.Count() > 1)
.Select(g = > g.Key);
您还可以随时添加扩展方法并从源
获取不同的值IEnumerable <TextEntry> distinctList = localTextEntries.DistinctBy(x = > x.Id);
public static IEnumerable<TSource> Distinctify<TSource, TKey>(this IEnumerable<TSource> inSrc_, Func<TSource, TKey> keyFunct_)
{
var uniqueSet = new HashSet<TKey>();
return inSrc_.Where(tmp => uniqueSet.Add(keyFunct_(tmp)));
}
答案 1 :(得分:2)
您可以重新编写ToDictionary
以使用您自己的实现,其中包含异常消息中的key
:
//TODO come up with a slightly better name
public static Dictionary<TKey, TValue> MyToDictionary<TSource, TKey, TValue>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TValue> valueSelector,
IEqualityComparer<TKey> comparer)
{
comparer = comparer ?? EqualityComparer<TKey>.Default;
var dictionary = new Dictionary<TKey, TValue>(comparer);
foreach (var item in source)
{
var key = keySelector(item);
try
{
dictionary.Add(key, valueSelector(item));
}
catch (ArgumentException ex)
{
throw new ArgumentException("Missing key: " + key, ex);
}
}
return dictionary;
}
您需要在没有比较器或值选择器的情况下创建重载,其中使用这些参数的默认值。
您可能还想创建一种新的Exception
类型,它将密钥存储为属性,而不是在异常消息中包含密钥的字符串值(如果没有良好的字符串表示形式)对象)。
答案 2 :(得分:0)
您可以使用分组来检查重复或不重复的项目。要创建字典,请在分组的项目上运行ToDictionary
方法:
// get repeated items
var repeated = localTextEntries.GroupBy(t => t.Id).Where(g => g.Count() > 1).Select(i => i);
// get not repeated items
var notRepeated = localTextEntries.GroupBy(t => t.Id).Where(g => g.Count() == 1).Select(i => i.First());
// find not repeated items and create a dictionary
var dictFromNotRepeated = localTextEntries.GroupBy(t => t.Id)
.Where(g => g.Count() == 1)
.ToDictionary(g => g.Key, g => g.First());
答案 3 :(得分:0)
最后@Servy的方法最适合我。我刚刚选择了匹配的重载并添加了一些更好的错误处理:
public static Dictionary<TKey, TSource> ToDictionary2<TSource, TKey>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
IEqualityComparer<TKey> comparer = null)
{
comparer = comparer ?? EqualityComparer<TKey>.Default;
Dictionary<TKey, TSource> dictionary =
new Dictionary<TKey, TSource>(comparer);
foreach (var item in source)
{
var key = keySelector(item);
try
{
dictionary.Add(key, item);
}
catch (Exception ex)
{
string msg = string.Format("Problems with key {0} value {1}",
key,
item);
throw new Exception(msg, ex);
}
}
return dictionary;
}