今天在使用 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. Number Sequence(poj 1019)

    题意: 有一串数字串,其规律为 1 12 123 1234 12345 123456 1234567 12345678 123456789 12345678910 1234567891011 1234 ...

  2. poj 3168 Barn Expansion

    Barn Expansion Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 2465   Accepted: 666 Des ...

  3. JavaWeb学习总结(十三)——使用Session防止表单重复提交(转)

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

  4. Codeforces989E. A Trance of Nightfall

    $n \leq 200$个平面上的点,$q \leq 200$次询问:重复操作$m \leq 10000$次,到达点$x$的概率最大是多少.操作:一开始选点$P$,不一定要是给定点,可以是平面上任一点 ...

  5. vue2 父子组件间通信

    父组件往子组件传值 props 传text father.vue <template> <div class="father"> {{'我是父组件'}} & ...

  6. react-highcharts

    import ReactHighcharts from'react-highcharts'; class SummaryLeft extends Component { render () {var ...

  7. SpringCloud 分布式事务解决方案

    目录 TX-LCN分布式事务框架 TX-LCN分布式事务框架 随着互联化的蔓延,各种项目都逐渐向分布式服务做转换.如今微服务已经普遍存在,本地事务已经无法满足分布式的要求,由此分布式事务问题诞生. 分 ...

  8. 投影纹理映射(Projective Texture Mapping) 【转】

    摘抄“GPU Programming And Cg Language Primer 1rd Edition” 中文名“GPU编程与CG语言之阳春白雪下里巴人”  投影纹理映射( Projective ...

  9. 怎样使用oracle 的DBMS_SQLTUNE package 来执行 Sql Tuning Advisor 进行sql 自己主动调优

     怎样使用oracle 的DBMS_SQLTUNE package 来执行 Sql Tuning Advisor 进行sql 自己主动调优 1>.这里简单举个样例来说明DBMS_SQLTUN ...

  10. Ffmpeg 实现文件切割

    文件切割是一项很常见的基本功能,通过Ffmpeg可以很容易实现这项功能. 首先介绍下基本原理,文件切割说白了就过滤掉文件的部分音视频包,按照什么规则过滤呢? 答案是时间戳.文件中每个视频及音频包都有时 ...