Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if a list of integers increments by one

Tags:

c#

list

linq

Is there a way, with LINQ, to check if a list of integers are "sequential" - ie 1,2,3,4,5 or 14,15,16,17,18?

like image 820
Wilson Avatar asked Apr 10 '13 00:04

Wilson


3 Answers

You could do this via Enumerable.Zip:

bool sequential = values.Zip(values.Skip(1), (a,b) => (a+1) == b).All(x => x);

This works by taking each pair of values, and checking to see if the second is 1 more than the first, and returning booleans. If all pairs fit the criteria, the values are sequential.


Given that this is a list of integers, you can do this slightly more efficiently using:

bool sequential = values.Skip(1).Select((v,i) => v == (values[i]+1)).All(v => v);

This will only work on sequences which can be accessed by index. Note that we use values[i], not values[i-1], as the Skip call effectively shifts the indices.

like image 51
Reed Copsey Avatar answered Nov 08 '22 16:11

Reed Copsey


bool isSequential = Enumerable.Range(values.Min(), values.Count())
                              .SequenceEqual(values);
like image 23
Jacob Seleznev Avatar answered Nov 08 '22 14:11

Jacob Seleznev


One more option is to use Aggregate to iterate sequence only once.

Note that unlike All suggested by Reed Copsey Aggregate can't stop in the middle when condition fails...

var s = new int[] {3,4,5,6}.ToList();

var isSequential = s.Aggregate
  (
      new {PrevValue = 0, isFirst = true, Success = true} ,
      (acc, current) => 
          new {
                  PrevValue = current,
                  isFirst = false, 
                  Success = acc.Success && (acc.isFirst || (acc.PrevValue == current - 1))
               }
  )
  .Success;

Fancier version would be to have iterator that carries previous value along or special code that would split iterator on "First and the rest" allowing to implement Reed's solution with single iteration for any enumerable.

like image 2
Alexei Levenkov Avatar answered Nov 08 '22 14:11

Alexei Levenkov