分割List< int>分成连续的数字组 [英] Split a List<int> into groups of consecutive numbers

查看:113
本文介绍了分割List< int>分成连续的数字组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个排序的List<int>,例如{ 1, 2, 3, 4, 6, 7, 9 }
我想将其分为几组-每个组都有这样的连续数字:{ {1, 2, 3, 4}, {6, 7}, {9} }

I have a sorted List<int> like { 1, 2, 3, 4, 6, 7, 9 }
I want to split that into some groups -- every group has consecutive number like this: { {1, 2, 3, 4}, {6, 7}, {9} }

我知道我可以使用for循环遍历列表,并在当前值和上一个值之间进行比较,然后决定是追加到最后一个组还是创建一个新组.但我想找到一种漂亮"的方法.也许使用LINQ?

I know I can use for loop to traverse the list, and compare between the current value and previous value, then decide whether append to last group or create a new group. But I want to find a "pretty" way to do it. Maybe use LINQ?

我从项目 more-itertools找到了python代码:

def consecutive_groups(iterable, ordering=lambda x: x):
    for k, g in groupby(
        enumerate(iterable), key=lambda x: x[0] - ordering(x[1])
    ):
        yield map(itemgetter(1), g)

推荐答案

以下是我对使用迭代器的扩展方法的建议:

Here is my suggestion for an extension method using iterators:

public static IEnumerable<IEnumerable<int>> GroupConsecutive(this IEnumerable<int> src) {
    var more = false; // compiler can't figure out more is assigned before use
    IEnumerable<int> ConsecutiveSequence(IEnumerator<int> csi) {
        int prevCurrent;
        do
            yield return (prevCurrent = csi.Current);
        while ((more = csi.MoveNext()) && csi.Current-prevCurrent == 1);
    }

    var si = src.GetEnumerator();
    if (si.MoveNext()) {
        do
            // have to process to compute outside level  
            yield return ConsecutiveSequence(si).ToList();
        while (more);
    }
}

我必须说Python算法令人印象深刻,这是它的C#实现:

I must say the Python algorithm is very impressive, here is a C# implementation of it:

public static IEnumerable<IEnumerable<int>> GroupConsecutive(this IEnumerable<int> iterable, Func<int,int> ordering = null) {
    ordering = ordering ?? (n => n);
    foreach (var tg in iterable
                         .Select((e, i) => (e, i))
                         .GroupBy(t => t.i - ordering(t.e)))
        yield return tg.Select(t => t.e);
}

这是Python算法的C#单行实现:

Here is a C# one-line implementation of the Python algorithm:

public static IEnumerable<IEnumerable<int>> GroupConsecutive(this IEnumerable<int> iterable, Func<int,int> ordering = null) => 
    iterable
      .Select((e, i) => (e, i))
      .GroupBy(
        t => t.i - (ordering ?? (n => n))(t.e),
        (k,tg) => tg.Select(t => t.e));

注意:启用了可空注释上下文的C#8应该在两个Python方法中都使用Func<int,int>?.您还可以使用??=分配ordering.

NOTE: C# 8 with nullable annotation context enabled should use Func<int,int>? in both Python methods. You could also use ??= to assign ordering.

这篇关于分割List&lt; int&gt;分成连续的数字组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆