LINQ找到一系列连续数字

Joh*_*ies 5 c# linq algorithm list

我有一个整数列表.我想在该列表中找到所有连续数字的运行,由起始索引和长度定义.因此,例如,对于输入列表[1,2,3,5,7,8],输出将是[{1,3}, {5,1}, {7,2}].这很容易使用循环,类似这样(未经测试的伪代码):

for(i=1, i < maxNum; i++)
{
  number = list[i];
  previousNumber = list[i-1];
  if(number - previousNumber == 1)
  {
    runLength++;
  }
  else
  {
    result.Add(startingNumber, runLength);
    runLength = 1;
    startingNumber = number;
  }
}
Run Code Online (Sandbox Code Playgroud)

但我认为可以使用LINQ.任何想法如何做到这一点?

L.B*_*L.B 8

一种linqish方式可以编写 GroupWhile如下所示的扩展方法(省略所有检查.未优化以便于理解.)

int[] list = new int[] { 1, 2, 3, 5, 7, 8 };
var result = list.GroupWhile((x, y) => y - x == 1)
                 .Select(x => new {i = x.First(), len = x.Count()  })
                 .ToList();
Run Code Online (Sandbox Code Playgroud)
public static IEnumerable<IEnumerable<T>> GroupWhile<T>(this IEnumerable<T> seq, Func<T,T,bool> condition)
{
    T prev = seq.First();
    List<T> list = new List<T>() { prev };

    foreach(T item in seq.Skip(1))
    {
        if(condition(prev,item)==false)
        {
            yield return list;
            list = new List<T>();
        }
        list.Add(item);
        prev = item;
    }

    yield return list;
}
Run Code Online (Sandbox Code Playgroud)

TODO:用IGrouping:)

  • 1) 这是多次迭代源序列 2) 由于分组都是对同一个确切列表的引用,如果在生成下一组之前没有处理每个组,则会导致重大问题。一个简单的`GroupWhile(...).ToList()` 将导致一堆对同一组的引用。您应该为每个组创建一个新列表。3) 在 `foreach` 结束时,该组将始终至少有一个项目,从不为零,因此无需检查计数。 (2认同)
  • OMG条件(prev,item)== false (2认同)

Vin*_*ele 6

这似乎是一个合理的方法:

  1. 用 a 压缩原始列表Range,因此每个元素都与其索引元组
  2. 选择列表前驱不是其自然前驱的元素
  3. 转换为数组并保存为临时变量(方便最后一步)。
  4. 从索引推导出子数组的长度。对于最后一项,它是与原始列表长度的差异。对于其他项目,它是与下一个索引的差异。

var list = new int[] { 1, 2, 3, 5, 7, 8 };
var filtered = list.Zip(Enumerable.Range(0, list.Length), Tuple.Create)
            .Where((x, i) => i == 0 || list[i - 1] != x.Item1 - 1).ToArray();

var result = filtered.Select((x, i) => i == filtered.Length - 1 
                ? Tuple.Create(x.Item1, list.Length - x.Item2) 
                : Tuple.Create(x.Item1, filtered[i + 1].Item2 - x.Item2));

foreach (var t in result)
{
    Console.WriteLine(t);
}
Run Code Online (Sandbox Code Playgroud)

这导致

(1, 3)
(5, 1)
(7, 2)
Run Code Online (Sandbox Code Playgroud)