今天在使用 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. idea部署项目到远程tomcat

    之前做项目,一直都是把本地的源码上传到svn,服务器是通过ant或者maven脚本来编译的生成项目的.每次都要单独登录接服务器进行项目的部署和发布,感觉特别繁琐.(特别是在有几套服务器的情况下,简直就 ...

  2. bzoj 3000 Big Number 估算n!在k进制下的位数 斯特林公式

    题目大意 求n!在k进制下的位数 2≤N≤2^31, 2≤K≤200 分析 作为数学没学好的傻嗨,我们先回顾一下log函数 \(\log_a(b)=\frac 1 {log_b(a)}\) \(\lo ...

  3. HTML-loading动画1

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  4. python笔记3:注释命名风格

    6.注释: 行注释采用  # 开头,多行注释使用三个单引号 (''') 或三个双引号 ("' '"),注释不需要对齐 三引号让程序员从引号和特殊字符串的泥潭里面解脱出来,自始至终保 ...

  5. L1-1. 出生年【STL放的位置】

    L1-1. 出生年 时间限制 400 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 以上是新浪微博中一奇葩贴:“我出生于1988年,直到25岁才 ...

  6. 牛客网 牛客练习赛7 D. 珂朵莉的无向图(多源BFS)

    题目链接  Problem D 比赛的时候完全想不到 直接对给定的这些点做多源$BFS$,把给定的这些点全都压到队列里,然后一个个做. 最后统计被访问的点的个数即可. #include <bit ...

  7. python安装numpy和matplotlib

    1.从该链接下载对应的whl文件 2.按照下面的方式从whl文件安装即可 windows7 python2.7 1.用管理员方式打开cmd 2.首先通过pip命令安装wheel 如果提示’pip’不是 ...

  8. guava之cache

    转自:http://ifeve.com/google-guava-cachesexplained/ 范例 01 LoadingCache<Key, Graph> graphs = Cach ...

  9. 信号板拼包:数组方式(bug长度只是截短,并未清空,若之后拷贝数据长度小于之前数据长度,老数据会接在后面)

    class SignalobardMsgReadHandler : public SessionVectChar::ReadHandler{public:  SignalobardMsgReadHan ...

  10. 把Execl表格中的数据获取出来保存到数据库中

    比如我们遇到一些需要把execl表格中的数据保存到数据库中,一条一条保存效率底下而且容易出错,数据量少还好,一旦遇到数据量大的时候就会累死个人啊,下面我们就来把execl表格中数据保存到对应的数据库中 ...