如何根据linq和c#列中的行之间的差异进行分组?

时间:2016-07-27 14:51:36

标签: c# linq group-by

我希望在行中的值之间的差异大于5时创建一个新组。

示例:

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

应该给我3组:

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

可以在这里使用Linq吗?

THX!

3 个答案:

答案 0 :(得分:4)

利用副作用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]

答案 1 :(得分: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();

答案 2 :(得分:2)

在我看来,只需编写一个函数来完成它。这比其他答案中给出的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()