【问题标题】:How do I use LINQ to compare one value from its previous value?如何使用 LINQ 将一个值与之前的值进行比较?
【发布时间】:2014-08-15 22:24:53
【问题描述】:

以下代码:

        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));

但这究竟是如何工作的呢?

【问题讨论】:

  • 嗯...当您运行它时,它不会在第三行(dic[1].Add(10);)抛出越界异常吗?
  • 我将从简单的任务开始 - 检查列表是否有两个连续的重复值。不要用字典使问题复杂化
  • 我觉得使用简单的forforeach 循环会更容易。
  • 旁注:Dictionary 正式来说没有“跟随”的概念,因为它是无序结构。

标签: c# .net linq list


【解决方案1】:

您可以检查列表是否有两个连续的重复

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) =&gt; x == y 应用于两个序列的对应元素。这两个序列是列表,同一个列表向前移动了一项。 IE。您正在将功能应用于同一列表的 indexindex + 1 项目。此函数产生项目比较的结果。因此,Zip 将根据连续项目的相等性返回truefalse 的序列。如果结果中有任何true,那么您有两个连续的重复项。

分步示例:考虑以下列表9, 10, 9, 7, 7。如果您跳过此列表中的第一项,您将获得序列10, 9, 7, 7。这两个序列的压缩将产生以下项目对(您应该画出相应的项目 - 第一个和第一个,第二个和第二个等):(10, 9), (9, 10), (7,9), (7,7)。下一步是将(x,y) =&gt; x == y 函数应用于每一对。结果将是false, false, false, true。如您所见,最后一对(第一个序列的第四个项目和第二个序列的第四个项目)具有相等的项目,因此它产生true。最后一件事是检查是否有任何对产生true

【讨论】:

  • Zip 扩展方法是 Linq 家族中使用最少的扩展方法之一。因此,对未来的访客来说,一点点解释都会有很长的路要走。否则,这是一个很好的答案。
  • +1 在这种情况下你可以调用 Any 没有参数
  • @BlackBear 不,你不能。如果没有参数,它将验证序列是否不为空,而不是它是否包含任何值 true
  • @BartoszKP 是的,这意味着为时已晚,我应该去睡觉了:p
  • @BlackBear 我会删除我的 cmets,不要制造不必要的噪音 :)
猜你喜欢
  • 1970-01-01
  • 2020-03-24
  • 1970-01-01
  • 2015-09-19
  • 1970-01-01
  • 2015-12-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多