Sagnik Chakraborti Sagnik Chakraborti - 8 days ago 6
Javascript Question

Find if an array's elements are in sequence

var arr = ["3","5","4","6"];
arr.sort();

var flag = 0;

for(var i = 1; i < arr.length; i++) {
if(arr[i] - arr[i-1] != 1 ) {
flag = 1;
break;
}
}

if(flag == 1){
alert('not in sequence');
}else{
alert('in sequence');
}


Here, the loop breaks only if the array is not in sequence.

I want to break the loop if an array is in sequence.

Here's why.

I have 4 arrays. I want to end the loop if any one of the 4 arrays is in sequence

var arr1 = ["4","1","3","5"];
var arr2 = ["5","2","3","6"];
var arr3 = ["1","5","3","6"];
var arr4 = ["1","5","3","4"];


arr1.sort();
arr2.sort();
arr3.sort();
arr4.sort();


var flag = 0;


for(var i = 1; i < 5; i++){

if(flag == 0){
for(var j = 1; i < eval('arr'+i).length; j++) {
if(eval('arr'+i)[j] - eval('arr'+i)[j-1] != 1) {
flag = 0;
}else{
flag = 1;
break;
}
}
}

}


if(flag == 1){
alert('in sequence');
}else{
alert('not in sequence');
}


Here, I'm trying to set flag to 1 if in sequence so that it does not enter the loop again.

It's always printing
in sequence
.

Answer

Iterate your arrays using Array#some. As soon as one of them is in sequence (inSeq() returns true), Array#some will return the true. Of all of them will fail, Array#some will return false. I'm using Array#every in the inSeq() function to check that the elements increment. If an increment is not 1, the loop returns false immediately:

var arr1 = ["4", "1", "3", "5"];
var arr2 = ["5", "2", "3", "6"];
var arr3 = ["1", "5", "3", "6"];
var arr4 = ["1", "5", "3", "4"];

function inSeq(arr) {
  return arr.sort(function(a, b) { return a - b; }) // the sort function is needed because you use strings instead of numbers, and it will be sorted lexicaly without the function.
    .every(function(n, i, arr) {
      return i === 0 || n - arr[i - 1] === 1;
    });
}

var result = [arr1, arr2, arr3, arr4].some(inSeq);

console.log(result);

And the shorter ES6 version using arrow functions:

const arr1 = ["4", "1", "3", "5"];
const arr2 = ["5", "2", "3", "6"];
const arr3 = ["1", "5", "3", "6"];
const arr4 = ["1", "5", "3", "4"];

const inSeq = (input) => input.sort((a, b) => a - b)
  .every((n, i, arr) => i === 0 || n - arr[i - 1] === 1);

const result = [arr1, arr2, arr3, arr4].some(inSeq);

console.log(result);

If you want to get the 1st array with a sequence, Array#some won't help you (unless you add some ugly code), as it returns a boolean. You can use a simple for loop:

var arr1 = ["4", "1", "3", "5"];
var arr2 = ["5", "4", "3", "6"];
var arr3 = ["1", "5", "3", "6"];
var arr4 = ["1", "5", "3", "4"];

function inSeq(arr) {
  return arr.sort(function(a, b) { return a - b; }) // the sort function is needed because you use strings instead of numbers, and it will be sorted lexicaly without the function.
    .every(function(n, i, arr) {
      return i === 0 || n - arr[i - 1] === 1;
    });
}

function findArrWithSeq(arrs) {
  for(var i = 0; i < arrs.length; i++) {
    if(inSeq(arrs[i])) {
       return i;
    }
  }
  
  return null;
}

var result = findArrWithSeq([arr1, arr2, arr3, arr4]);

console.log(result);