今天在使用 Linq 的 ToDictionary() 时发生了异常,提示:

System.ArgumentException: 已添加了具有相同键

因为以前一直没有遇到有相同键的情况,所以从来没关注过这个问题。然后写段试验来码来处理这个问题

问题再现

csclass Program
{
public static void Main(string[] args)
{
var data = new[]{
Tuple.Create("001", "James"),
Tuple.Create("002", "Linda"),
Tuple.Create("003", "Frank"),
Tuple.Create("004", "Jack"),
Tuple.Create("002", "Rose"),
Tuple.Create("001", "Lynn"),
Tuple.Create("008", "Luke")
};
var dict = data.ToDictionary(t => t.Item1, t => t.Item2);
// 这里就抛异常了
// System.ArgumentException: 已添加了具有相同键的
foreach (var pair in dict)
{
// 不要见怪,用了 C# 6.0 的语法
Console.WriteLine($"{pair.Key} = {pair.Value}");
}
}
}

使用 ToLookup() 解决

原来 ToDictionary() 不会处理重复键,也没有提供多的参数来处理重复键。想了一下,这种问题大概应该用 ToLookup() 来解决,所以改写了代码

cs        // var dict = data.ToDictionary(t => t.Item1, t => t.Item2);
// System.ArgumentException: 已添加了具有相同键的 var dict = data.ToLookup(t => t.Item1, t => t.Item2)
.ToDictionary(t => t.Key, t => t.First());

ToLookup() 返回的是一个 ILookup<> 接口,看定义是一个 IGrouping<> 接口的枚举。 IGrouping<> 本身也是一个 IEnumerable<> ,具有 Key 属性。因为 IGrouping<> 将具有同一个键的所有元素都包含在内了,所以在生成 Dictionary 的时候只取其中一个元素,根据上下文需要,可以取 First() ,或者 Last() 。

这是 ILookup<> 和 IGrouping<> 的定义

cspublic interface ILookup<TKey, TElement>
: IEnumerable<IGrouping<TKey, TElement>>, IEnumerable public interface IGrouping<out TKey, out TElement>
: IEnumerable<TElement>, IEnumerable

自定义 ToDictionaryEx() 来解决

因为 ToLookup() 返回的结果包含太多枚举对象,所以不知道性能如何。如果不放心,可以自己写个 ToDictionaryEx() 来解决,当然也不敢保证性能就比 ToLookup() 好,要实验了才知道。

csstatic class ToDictionaryExtentions
{
public static IDictionary<TKey, TValue> ToDictionaryEx<TElement, TKey, TValue>(
this IEnumerable<TElement> source,
Func<TElement, TKey> keyGetter,
Func<TElement, TValue> valueGetter)
{
IDictionary<TKey, TValue> dict = new Dictionary<TKey, TValue>();
foreach (var e in source)
{
var key = keyGetter(e);
if (dict.ContainsKey(key))
{
continue;
}
dict.Add(key, valueGetter(e));
}
return dict;
}
}

现在实验代码又该改改了

cs        // var dict = data.ToDictionary(t => t.Item1, t => t.Item2);
// System.ArgumentException: 已添加了具有相同键的 //var dict = data.ToLookup(t => t.Item1, t => t.Item2)
// .ToDictionary(t => t.Key, t => t.First()); var dict = data.ToDictionaryEx(t => t.Item1, t => t.Item2);

性能

没有测试性能的问题,等暴露了性能问题再来测试吧

解决Linq.ToDictionary()时的键重复问题的更多相关文章

  1. mysql insert插入时实现如果数据表中主键重复则更新,没有重复则插入的四种方法

    [CSDN下载] Powerdesigner 设计主键code不能重复等问题 [CSDN博客] Oracle中用一个序列给两个表创建主键自增功能的后果 [CSDN博客] MySQL自增主键删除后重复问 ...

  2. Linux下Oracle中SqlPlus时上下左右键乱码问题的解决办法

    window下的sqlplus可以通过箭头键,来回看历史命令,用起来非常的方便. 但是在Linux下,会出现各种乱码,非常不方便,如下图所示,每次打错一个字符就需要重新打一遍. 解决办法:rlwrap ...

  3. (转)mysql自增列导致主键重复问题分析

    mysql自增列导致主键重复问题分析...  原文:http://www.cnblogs.com/cchust/p/3914935.html 前几天开发童鞋反馈一个利用load data infile ...

  4. (2.10)Mysql之SQL基础——约束及主键重复处理

    (2.10)Mysql之SQL基础——约束及主键重复处理 关键词:mysql约束,批量插入数据主键冲突 [1]查看索引: show index from table_name; [2]查看有约束的列: ...

  5. C# Dictionary<TKey,TValue>如何添加键重复的内容

    这里以Dictionary<string,string>为例 当我们实例化Dictionary<string,string>集合时,其中有一个重载构造方法如下: // // 摘 ...

  6. Entity Framework Code First 在Object Join Linq查询时出现全表查询的语句。

    最近一个项目,使用微软的Entity Framework的ORM框架的项目,部署到现场后,出现了系统缓慢,多个客户端的内存溢出崩溃的问题. 打开了SQL Server Profiler(SQL Ser ...

  7. 【Transact-SQL】SQL Server自动把left join自动转化为inner join、以及关联时的数据重复问题

    原文:[Transact-SQL]SQL Server自动把left join自动转化为inner join.以及关联时的数据重复问题 1.SQL Server自动把left join自动转化为inn ...

  8. 使用sequelize-auto 生成mysql 表的实体时主键没有 autoIncrement: true 属性

    使用sequelize-auto 生成mysql 表时主键没有 autoIncrement: true 属性,这会导致插入数据时报错.看git上面是已经解决了的,解决方法是修改查询语句模板.我用的是0 ...

  9. 解决安装mysql时出现的三种问题

    MySQL v5.0.96 for windows 安装版         链接:http://pan.baidu.com/s/1slmE2k9 密码:tadp MySQLAdministratort ...

随机推荐

  1. poj 3109

                                                                                                         ...

  2. C语言第五题

    学生成绩管理系统 一.登录页面分为:首页展示学生登录和老师登录让用户选择,选择完以后提示用户输入账户名和密码 ps:1.老师的账户目前就一个,账户密码可以设置成admin/admin 2.学生的账户是 ...

  3. JSON 序列化与弱类型

    一.C#中JSON序列化有多种方式: 使用“DataContractJsonSerializer ”类时需要, 1.引用程序集 System.Runtime.Serialization 和 Syste ...

  4. C和C++内存分配方式记录

    C. C++中内存分配方式可以分为三种: (1)从静态存储区域分配:内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在.速度快.不容易出错,因为有系统会善后.例如全局变量,static变 ...

  5. py2exe使用方法 (含一些调试技巧,如压缩email 类)

    http://justcoding.iteye.com/blog/900993 一.简介 py2exe是一个将python脚本转换成windows上的可独立执行的可执行程序(*.exe)的工具,这样, ...

  6. LeetCode OJ--Next Permutation *

    求一个排列的下一个排列. 1,2,3 → 1,3,23,2,1 → 1,2,31,1,5 → 1,5,1 #include <iostream> #include <vector&g ...

  7. Java原来如此-随机数

    在Java中,生成随机数有两种方法.1是使用Random类.2是使用Math类中的random方法. 我们现在做个例子,比如生成20个0到10之间的随机数. 1.使用Random类的nextInt(n ...

  8. DOS底下常用命令

    DOS底下常用命令: dir (directory) :列出当前目录下的文件以及文件夹 md (make directory): 创建目录 rd (remove directory):删除目录 cd ...

  9. Codeforces Gym101572 B.Best Relay Team (2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017))

    2017-2018 ACM-ICPC Nordic Collegiate Programming Contest (NCPC 2017) 今日份的训练,题目难度4颗星,心态被打崩了,会的算法太少了,知 ...

  10. pycharm上传代码到码云(详细)

    如要转载 麻烦请您备注好原文出处!!!!(谢谢合作!) >>首先要去码云注册个账号 提示(尽量使用英文名)创建用户名 使用邮箱登录 >>然后创建库  >填写项目的基础信息 ...