我怀疑这是您使用 LINQ 的地方:
一个由排序的唯一数字组成的数组
var ints = new[] {
1, 2, 3,
5, 6,
8, 9, 10, 11,
15, 16, 17,
20, 21, 22,
25,
27,
30, 31
};
还有一个收集连续数据的 LINQ:
var consecs = ints
.Select((item, idx) => new { I = item, G = item - idx })
.GroupBy(
ig => ig.G,
ig => ig.I,
(k, g) => g.ToArray()
)
.Where(a => a.Length > 1)
.ToArray();
它是如何工作的?
- Select 生成一个新对象,该对象从 0 开始对数组中的整数进行编号,即您在
item 中获得数字本身,在 idx 中获得它的索引。我们从数字中减去 idex。因为索引每次递增 1,所以每次也递增 1 的任何数字运行都将为 G 生成一个固定值:
-
item == 1, idx == 0, G == 1, item == 2, idx == 1, G == 1, item == 3, idx == 2, G == 1,
-
item == 5, idx == 3, G == 2, item == 6, idx == 4, G == 2,
- 等等
- 该组有 3 个参数:
- 分组依据:
ig => ig.G - 按 G 分组,这使得 LINQ 将同一 G 中的所有项目收集到一个列表中。输入参数称为ig,因为它是I和G的匿名类型
- 在 list-of-I-with-same-G 中放入什么:
ig => ig.I - 只是 I 项,这意味着输出将是一个整数列表,即原始项
- 如何处理输出列表:
(k, g) => g.ToArray() - 将其从分组转换为数组。 k是分组键(以前叫G);我们不需要它。 g 是 groupby 用相同 G 收集的数字列表。它通常是一个 Grouping,但我们可以在这个阶段将其转换为 int[]
- 然后我们运行
Where 以排除仅包含一项的数组,因为它们不是两个或多个数字的连续运行。该组输出Enumerable<int[]> 所以a 是int[]
- ToArray 最后只是将数组的可枚举(为我们过滤的位置)转换为数组数组,因此输出为
int[][]
这意味着您最终会得到以下组:
consecs[0] -> new [] { 1,2,3 };
consecs[1] -> new [] { 5,6 };
consecs[2] -> new [] { 5,6 };
--
所以你想在没有 LINQ 的情况下这样做?
好的,让我们使用Dictionary<int,List<int>> 来收集同一组号下的项目。我们将像以前一样从 item-index 计算字典的键,并确保它作为新列表存在,然后我们将向其中添加项目。然后我们将跳过任何只有 1 大的列表
var ints = new[] {
1, 2, 3,
5, 6,
8, 9, 10, 11,
15, 16, 17,
20, 21, 22,
25,
27,
30, 31
};
var d = new Dictionary<int, List<int>>();
for(int idx = 0; idx < ints.Length; idx++){
var g = ints[idx] - idx;
d.TryAdd(g, new List<int>()); //make sure a list exists for g; does nothing if g is known
d[g].Add(ints[idx]);
}
foreach(var kvp in d){
if(kvp.Value.Count == 1)
continue; //skip lists of only one item
//do whatever with your list of consecutive ints
}