【问题标题】:How can I group by the difference between rows in a column with linq and c#?如何使用 linq 和 c# 按列中的行之间的差异进行分组?
【发布时间】:2016-07-27 14:51:35
【问题描述】:

当行中的值之间的差异大于 5 时,我想创建一个新组。

例子:

int[] list = {5,10,15,40,45,50,70,75};

应该给我3组:

1,[ 5,10,15 ]
2,[40,45,50]
3,[70,75]

这里可以使用Linq吗?

谢谢!

【问题讨论】:

  • 您在这里尝试使用 LINQ 是否有特定原因?到目前为止,您尝试了什么?
  • 我试图用一个循环来解决这个问题(还没有完成......)。但是,当我在编写循环时,它对我来说似乎不是一个优雅的解决方案:/

标签: c# linq group-by


【解决方案1】:

利用副作用 (group) 不是一个好习惯,但可能会有所帮助:

  int[] list = { 5, 10, 15, 40, 45, 50, 70, 75 };

  int step = 5;
  int group = 1;

  var result = list
    .Select((item, index) => new {
               prior = index == 0 ? item : list[index - 1],
               item = item,
             })
    .GroupBy(pair => Math.Abs(pair.prior - pair.item) <= step ? group : ++group, 
             pair => pair.item);

测试:

  string report = string.Join(Environment.NewLine, result
    .Select(chunk => String.Format("{0}: [{1}]", chunk.Key, String.Join(", ", chunk))));

结果:

1: [5, 10, 15]
2: [40, 45, 50]
3: [70, 75]

【讨论】:

    【解决方案2】:

    假设集合定义了一个索引器,可以是这样的:

    const int step = 5;
    int currentGroup = 1;
    var groups = list.Select((item, index) =>
    {
        if (index > 0 && item - step > list[index - 1])
        {
            currentGroup++;
        }
        return new {Group = currentGroup, Item = item};
    }).GroupBy(i => i.Group).ToList();
    

    【讨论】:

      【解决方案3】:

      在我看来,只需编写一个函数即可。这比其他答案中给出的 Linq 示例更容易理解和可读。

      public static List<List<int>> Group(this IEnumerable<int> sequence, int groupDiff) {
          var groups = new List<List<int>>();
          List<int> currGroup = null;
          int? lastItem = null;
          foreach (var item in sequence) {
              if (lastItem == null || item - lastItem.Value > groupDiff) {
                  currGroup = new List<int>{ item };
                  groups.Add(currGroup);
              } else {
                  // add item to current group
                  currGroup.Add(item);
              }
              lastItem = item;
          }
          return groups;
      }
      

      然后这样称呼它

      List<List<int>> groups = Group(list, 5);
      

      假设:list 已排序。如果没有排序,就先排序,再使用上面的代码。

      另外:如果您需要 groups 成为 int[][],只需根据自己的喜好使用 Linq 方法 ToArray()

      【讨论】:

      • 我认为可读性取决于程序员。我使用 lambda 函数的次数越多,阅读起来就越容易。
      猜你喜欢
      • 2019-07-22
      • 1970-01-01
      • 1970-01-01
      • 2019-04-13
      • 1970-01-01
      • 1970-01-01
      • 2019-02-17
      • 2023-03-12
      • 1970-01-01
      相关资源
      最近更新 更多