简体   繁体   English

如何检查 int 类型的索引序列是否连续?

[英]How can I check that a sequence of indices of type int are contiguous?

I have a Column class which has an Index property of type int .我有一个Column类,它有一个int类型的Index属性。

If I have a collection of Column objects, I am looking for a way to test if their indices are contiguous.如果我有一组Column对象,我正在寻找一种方法来测试它们的索引是否连续。 By contiguous I mean that the indices are next to each other, so if ordered by value they are 1 apart from the next and previous Index.连续我的意思是索引彼此相邻,因此如果按值排序,它们与下一个和上一个索引的距离为 1。

There can be any number of column objects.可以有任意数量的column对象。

So, for example:因此,例如:

  • 10,11,12,13 => true 10,11,12,13 => 真

  • 3,5,7 => false 3,5,7 => 假

  • 1,2,4 => false 1,2,4 => 假

Edit编辑

While these examples are of ordered indices, I would like a solution that takes an unordered set of indices.虽然这些示例是有序索引,但我想要一个采用无序索引集的解决方案。

I feel sure there is probably a neat Linq way of solving this, but I cannot see it.我确信可能有一种简洁的 Linq 方法来解决这个问题,但我看不到它。

Expressed in code:用代码表示:

public class Column 
{
    public int Index { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        // Example set of columns 1
        List<Column> columns1 = new List<Column>()
        {
            new Column(){Index = 10},
            new Column(){Index = 11},
            new Column(){Index = 12},
            new Column(){Index = 13},
        };

        // Example set of columns 2
        List<Column> columns2 = new List<Column>()
        {
            new Column(){Index = 3},
            new Column(){Index = 5},
            new Column(){Index = 7},
        };

        // Example set of columns 3
        List<Column> columns3 = new List<Column>()
        {
            new Column(){Index = 1},
            new Column(){Index = 2},
            new Column(){Index = 4},
        };

        var result1 = IndicesAreContiguos(columns1); // => true
        var result2 = IndicesAreContiguos(columns2); // => false
        var result3 = IndicesAreContiguos(columns3); // => false
    }

    public bool IndicesAreContiguos(IEnumerable<Column> columns) 
    {
        // ....???
    }

}

With math you can create a function which will handle unordered collections with only one iteration over collection.使用数学,您可以创建一个函数,该函数将仅对集合进行一次迭代来处理无序集合。

public static bool IsConsecutive(this IEnumerable<int> values)
{
    return values
        .Aggregate((Sum: 0, Min: int.MaxValue, Max: int.MinValue, Count: 0), 
            (total, value) =>
            {
                total.Count += 1;
                total.Sum += value;
                total.Min = total.Min > value ? value : total.Min;
                total.Max = total.Max < value ? value : total.Max;

                return total;
            },
            (total) =>
            {
                var difference = total.Max - total.Min + 1;
                var expectedSum = (total.Count * (total.Min + total.Max)) / 2;

                return difference == total.Count && expectedSum == total.Sum;
            });
}

Solution is based on the formula of sum of consecutive integers (Gauss's Formula)解决方案基于连续整数之和的公式(高斯公式)

\\sum=\\frac{n(a_{1} + a_{n})}{2}

But because formula can be applied for consecutive integers with step other than 1 (for example 2, 4, 6, 8), we added check that step is only one by calculating difference between min and max values and comparing it with the quantity of values.但是因为公式可以应用于步长不是 1 的连续整数(例如 2、4、6、8),我们通过计算最小值和最大值之间的差异并将其与值的数量进行比较,添加了检查步长是否仅为 1 .

Usage用法

var values = new[] { 10, 12, 13, 15, 14, 11 };

if (values.IsConsecutive())
{
    // Do something
}

Give this a go:试一试:

public static bool IndicesAreContiguos(IEnumerable<Column> columns)
{
    var ordered = columns.Select(x => x.Index).OrderBy(x => x).ToArray();
    return ordered.Skip(1).Zip(ordered, (x, y) => x - y).All(z => z == 1);
}

This is literally "ordered by value they are 1 apart from the next and previous Index."这实际上是“按值排序,它们与下一个和上一个索引的距离为 1”。

You don't need LINQ for this你不需要 LINQ

public bool IsContig(int[] arr) {
  for(int i = 1; i<arr.Length;i++)
    if(arr[i] - arr[i-1] != 1)
      return false;
  return true;
}

LINQ is a hammer, but not every problem is a nail LINQ 是一把锤子,但不是每个问题都是钉子

(Edit: to accept an unordered set of indices, then consider a modification that sorts the array first. Again, LINQ isn't necessary; Array.Sort would work) (编辑:接受一组无序的索引,然后考虑首先对数组进行排序的修改。同样,LINQ 不是必需的;Array.Sort 会工作)

If a sequence of 1,2,3,2,3,2,3,4,3,2,3,4,5,4,5 is contiguous, improve the IF to allow for a result of -1 too如果 1,2,3,2,3,2,3,4,3,2,3,4,5,4,5 的序列是连续的,请改进 IF 以允许结果为 -1

One way would be to create a range from min to max and compare that to the existing indices:一种方法是创建从最小值到最大值的范围并将其与现有索引进行比较:

public static bool IndicesAreContiguos(IEnumerable<Column> columns)
{
    var orderedIndices = columns.Select(c => c.Index).OrderBy(i => i);
    if (orderedIndices.Distinct().Count() != columns.Count()) return false;  // Optional.

    int min = columns.Min(c => c.Index);
    int max = columns.Max(c => c.Index);

    return Enumerable.Range(min, max - min + 1).SequenceEqual(orderedIndices);
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM