以下代码:
Dictionary<int, List<int>> dic = new Dictionary<int, List<int>>();
dic.Add(1, new List<int>());
dic[1].Add(10);
dic[1].Add(6);
dic.Add(2, new List<int>());
dic[2].Add(9);
dic[2].Add(7);
dic[2].Add(7);
dic.Add(3, new List<int>());
dic[3].Add(9);
dic[3].Add(10);
dic[3].Add(9);
dic.Add(4, new List<int>());
dic[4].Add(6);
// Will give KVPs of Key 1 and 4
var under7 = dic.Where(T => T.Value.Any(Y => Y < 7));
所以我很容易发现哪些KVP的值低于7。
我的问题是如何迭代字典以查找具有重复值的KVP,其中一个键跟随另一个键(已按顺序)。
因为这应该被拿起来:
dic.Add(2, new List<int>());
dic[2].Add(9);
dic[2].Add(7); // MATCH
dic[2].Add(7); // MATCH
但不是这样:
dic.Add(3, new List<int>());
dic[3].Add(9); // NOT MATCH
dic[3].Add(10);
dic[3].Add(9); // NOT MATCH
有没有办法用LINQ做到这一点?
试图用下面的东西试一试,但很明显它并没有这样做。
// Should give KVP of Key 2 but not 3
var dupVals = dic.Where(T => T.Value.Aggregate( (i1, i2) => i1 == i2));
var dupVals = dic.Where(T => T.Value.Any( (i1,i2) => i1 == i2 ));
编辑: 谢尔盖得到了答案:
var result = dic.Where(kvp =>
kvp.Value.Skip(1).Zip(kvp.Value, (x, y) => x == y).Any(b => b));
但这究竟是如何运作的?
答案 0 :(得分:7)
您可以使用
检查列表是否有两个连续的重复项list.Skip(1).Zip(list, (x,y) => x == y).Any(b => b)
对字典中的每个值执行此操作:
// yep, you can use this pretty initializer
var dic = new Dictionary<int, List<int>> {
{ 1, new List<int> { 10, 6 }},
{ 2, new List<int> { 9, 7, 7 }},
{ 3, new List<int> { 9, 10, 9 }},
{ 4, new List<int> { 6 }}
};
var result = dic.Where(kvp =>
kvp.Value.Skip(1).Zip(kvp.Value, (x, y) => x == y).Any(b => b));
说明:Enumerable.Zip
扩展将指定函数(x,y) => x == y
应用于两个序列的相应元素。这两个序列是列表,并且相同的列表向前移动了一个项目。即您正在将函数应用于同一列表的index
和index + 1
项。此功能生成项目比较结果。因此,Zip将返回true
和false
的序列,具体取决于连续项的相等性。如果结果中有true
,那么您有两个连续的重复项。
分步示例:请考虑以下列表9, 10, 9, 7, 7
。如果您跳过此列表中的第一项,您将获得序列10, 9, 7, 7
。压缩这两个序列将产生以下项目对(您应该拍摄相应的项目 - 第一,第一,第二和第二等):(10, 9), (9, 10), (7,9), (7,7)
。下一步是将(x,y) => x == y
函数应用于每对。结果将为false, false, false, true
。如您所见,最后一对(第一个序列中的第四个项目和第二个序列中的第四个项目)具有相同的项目,因此它生成true
。最后一件事是检查是否有任何一对产生了true
。