【问题标题】:How to retrieve consecutive numbers from a list (not LINQ preferred)?如何从列表中检索连续数字(不是 LINQ 首选)?
【发布时间】:2022-01-19 13:16:04
【问题描述】:
List<int> ints = new List<int>();
ints.Add(1,5,6);

如何在新列表中获得 5 和 6?

我试过了,但是没用

List<int> newList = new List<int>();
newList = ints.Select((i, j) => i - j).Skip(1).ToList();

谢谢,请不要判断太苛刻,不是专家。

【问题讨论】:

  • 只是...var newList = ints.Skip(1).ToList()?不清楚为什么你有那个Select
  • not LINQ prefered - 使用LINQ ?!?
  • 你怎么知道你想要 5,6?按他们的立场?按他们的价值?您要完成的任务的一般说明是什么?如果您的意思是没有 LINQ,为什么您的示例代码显示 LINQ?你认为i - j 会为你做什么?

标签: c# list linq


【解决方案1】:

我建议把你的问题分成两个更简单的问题:

  1. 查找新的连续数字序列开始的所有索引。为此,请遍历列表并记住(= 放入新列表中)数字不等于前一个数字 + 1 的所有索引。

  2. 根据这些索引拆分您的列表。为此,请遍历您在第 1 步中创建的索引列表,并根据这些索引创建新列表。

【讨论】:

    【解决方案2】:

    我怀疑这是您使用 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 =&gt; ig.G - 按 G 分组,这使得 LINQ 将同一 G 中的所有项目收集到一个列表中。输入参数称为ig,因为它是I和G的匿名类型
      • 在 list-of-I-with-same-G 中放入什么:ig =&gt; ig.I - 只是 I 项,这意味着输出将是一个整数列表,即原始项
      • 如何处理输出列表:(k, g) =&gt; g.ToArray() - 将其从分组转换为数组。 k是分组键(以前叫G);我们不需要它。 g 是 groupby 用相同 G 收集的数字列表。它通常是一个 Grouping,但我们可以在这个阶段将其转换为 int[]
    • 然后我们运行Where 以排除仅包含一项的数组,因为它们不是两个或多个数字的连续运行。该组输出Enumerable&lt;int[]&gt; 所以aint[]
    • ToArray 最后只是将数组的可枚举(为我们过滤的位置)转换为数组数组,因此输出为int[][]

    这意味着您最终会得到以下组:

    consecs[0] -> new [] { 1,2,3 };
    consecs[1] -> new [] { 5,6 };
    consecs[2] -> new [] { 5,6 };
    

    --

    所以你想在没有 LINQ 的情况下这样做?

    好的,让我们使用Dictionary&lt;int,List&lt;int&gt;&gt; 来收集同一组号下的项目。我们将像以前一样从 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
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-06-28
      • 1970-01-01
      • 2021-09-17
      • 2017-11-13
      • 2017-10-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多