解决Linq.ToDictionary()时的键重复问题
今天在使用 Linq 的 ToDictionary()
时发生了异常,提示:
System.ArgumentException: 已添加了具有相同键
因为以前一直没有遇到有相同键的情况,所以从来没关注过这个问题。然后写段试验来码来处理这个问题
问题再现
cs
class 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<>
的定义
cs
public interface ILookup<TKey, TElement>
: IEnumerable<IGrouping<TKey, TElement>>, IEnumerable public interface IGrouping<out TKey, out TElement>
: IEnumerable<TElement>, IEnumerable
自定义 ToDictionaryEx() 来解决
因为 ToLookup()
返回的结果包含太多枚举对象,所以不知道性能如何。如果不放心,可以自己写个 ToDictionaryEx()
来解决,当然也不敢保证性能就比 ToLookup()
好,要实验了才知道。
cs
static 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()时的键重复问题的更多相关文章
- mysql insert插入时实现如果数据表中主键重复则更新,没有重复则插入的四种方法
[CSDN下载] Powerdesigner 设计主键code不能重复等问题 [CSDN博客] Oracle中用一个序列给两个表创建主键自增功能的后果 [CSDN博客] MySQL自增主键删除后重复问 ...
- Linux下Oracle中SqlPlus时上下左右键乱码问题的解决办法
window下的sqlplus可以通过箭头键,来回看历史命令,用起来非常的方便. 但是在Linux下,会出现各种乱码,非常不方便,如下图所示,每次打错一个字符就需要重新打一遍. 解决办法:rlwrap ...
- (转)mysql自增列导致主键重复问题分析
mysql自增列导致主键重复问题分析... 原文:http://www.cnblogs.com/cchust/p/3914935.html 前几天开发童鞋反馈一个利用load data infile ...
- (2.10)Mysql之SQL基础——约束及主键重复处理
(2.10)Mysql之SQL基础——约束及主键重复处理 关键词:mysql约束,批量插入数据主键冲突 [1]查看索引: show index from table_name; [2]查看有约束的列: ...
- C# Dictionary<TKey,TValue>如何添加键重复的内容
这里以Dictionary<string,string>为例 当我们实例化Dictionary<string,string>集合时,其中有一个重载构造方法如下: // // 摘 ...
- Entity Framework Code First 在Object Join Linq查询时出现全表查询的语句。
最近一个项目,使用微软的Entity Framework的ORM框架的项目,部署到现场后,出现了系统缓慢,多个客户端的内存溢出崩溃的问题. 打开了SQL Server Profiler(SQL Ser ...
- 【Transact-SQL】SQL Server自动把left join自动转化为inner join、以及关联时的数据重复问题
原文:[Transact-SQL]SQL Server自动把left join自动转化为inner join.以及关联时的数据重复问题 1.SQL Server自动把left join自动转化为inn ...
- 使用sequelize-auto 生成mysql 表的实体时主键没有 autoIncrement: true 属性
使用sequelize-auto 生成mysql 表时主键没有 autoIncrement: true 属性,这会导致插入数据时报错.看git上面是已经解决了的,解决方法是修改查询语句模板.我用的是0 ...
- 解决安装mysql时出现的三种问题
MySQL v5.0.96 for windows 安装版 链接:http://pan.baidu.com/s/1slmE2k9 密码:tadp MySQLAdministratort ...
随机推荐
- poj 3109
...
- C语言第五题
学生成绩管理系统 一.登录页面分为:首页展示学生登录和老师登录让用户选择,选择完以后提示用户输入账户名和密码 ps:1.老师的账户目前就一个,账户密码可以设置成admin/admin 2.学生的账户是 ...
- JSON 序列化与弱类型
一.C#中JSON序列化有多种方式: 使用“DataContractJsonSerializer ”类时需要, 1.引用程序集 System.Runtime.Serialization 和 Syste ...
- C和C++内存分配方式记录
C. C++中内存分配方式可以分为三种: (1)从静态存储区域分配:内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在.速度快.不容易出错,因为有系统会善后.例如全局变量,static变 ...
- py2exe使用方法 (含一些调试技巧,如压缩email 类)
http://justcoding.iteye.com/blog/900993 一.简介 py2exe是一个将python脚本转换成windows上的可独立执行的可执行程序(*.exe)的工具,这样, ...
- 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 ...
- Java原来如此-随机数
在Java中,生成随机数有两种方法.1是使用Random类.2是使用Math类中的random方法. 我们现在做个例子,比如生成20个0到10之间的随机数. 1.使用Random类的nextInt(n ...
- DOS底下常用命令
DOS底下常用命令: dir (directory) :列出当前目录下的文件以及文件夹 md (make directory): 创建目录 rd (remove directory):删除目录 cd ...
- 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颗星,心态被打崩了,会的算法太少了,知 ...
- pycharm上传代码到码云(详细)
如要转载 麻烦请您备注好原文出处!!!!(谢谢合作!) >>首先要去码云注册个账号 提示(尽量使用英文名)创建用户名 使用邮箱登录 >>然后创建库 >填写项目的基础信息 ...