For example,
const target = [1,2,3,4,5,"abc", "def"]
test(target, [2,3,4]) === true
test(target, [4,5,"abc"]) === true
test(target, [0,1,2]) === false
test(target, ["abc",5,4]) === false
test(target, [2,4]) === false
Currently I'm using JSON.stringify
to accomplish this (and with replacer
function if the elements contain things like BigInt
values):
`,${JSON.stringify(target).slice(1, -1)},`.includes(`,${JSON.stringify(arr).slice(1, -1)},`)
to check if target
contains arr
with the same ordering of elements, however this seems a bit too hacky so I wonder if there are better ways to accomplish it?
CodePudding user response:
To check for an ordered sub-array, including rejecting non-consecutive elements, we can use recursion: Array (A) is ordered inside another array (B) if first element of A is found, and if the rest of A, is inside the rest of B immediately after the found element.
function test(b, a, bIndex) {
if (!a.length) return true;
bIndex ??= b.findIndex(el => el === a[0]);
return a[0] !== b[bIndex] ? false : test(b.slice(bIndex 1), a.slice(1), 0);
}
const target = [1,2,3,4,5,"abc", "def"]
console.log(test(target, [2,3,4]) === true)
console.log(test(target, [4,5,"abc"]) === true)
console.log(test(target, [0,1,2]) === false)
console.log(test(target, ["abc",5,4]) === false)
console.log(test(target, [2,4]) === false)
The original version, that isn't sensitive to non-consecutive elements, relaxing the immediately after constraint.
function isOrderedSubArray(b, a) {
if (!a.length) return true;
let index = b.findIndex(el => el === a[0]);
return index === -1 ? false : isOrderedSubArray(b.slice(index 1), a.slice(1));
}
// testing it...
let bigArray = [0, 1, 2, 3, 4, 5, 6];
let smallA = [2, 5, 6];
let smallB = [2, 5, 12];
let smallC = [4, 3, 5];
let smallD = [6, undefined];
console.log(isOrderedSubArray(bigArray, smallA)===true)
console.log(isOrderedSubArray(bigArray, bigArray)===true)
console.log(isOrderedSubArray(bigArray, smallB)===false)
console.log(isOrderedSubArray(bigArray, smallC)===false)
console.log(isOrderedSubArray(bigArray, smallD)===false)
CodePudding user response:
You could get the start index and check every item of the second array.
const
test = (a, b) => {
let offset = a.indexOf(b[0]);
while (offset !== -1) {
if (b.every((v, i) => (i offset) in a && v === a[i offset])) return true;
offset = a.indexOf(b[0], offset 1);
}
return false;
},
target = [1, 2, 3, 4, 5, "abc", "def"];
console.log(test(target, [2, 3, 4])); // true
console.log(test(target, [4, 5, "abc"])); // true
console.log(test(target, [0, 1, 2])); // false
console.log(test(target, ["abc", 5, 4])); // false
console.log(test(target, [2, 4])); // false
console.log(test(target, [])); // false
console.log(test(target, [ "abc", "def", undefined])); // false
.as-console-wrapper { max-height: 100% !important; top: 0; }
CodePudding user response:
This could be tidied up but I think it will be quite performant.
- If the first element of the sub array does not appear in the target return false
- iterate over the target for the length of sub, from the starting position
x
- If the position of the sub element is not equal to its relative position in the target element, or we go beyond the length of the target array,
return false
- If all these checks pass
return true
const target = [1,2,3,4,5,"abc", "def"]
function test(arr, sub) {
x = arr.indexOf(sub[0])
if(x < 0) return false;
i = 0
while(i < sub.length ) {
if(i != sub.indexOf(arr[x],i) || x >= arr.length) return false;
x =1
i =1
}
return true
}
console.log(test(target, [2,3,4]))// === true
console.log(test(target, [4,5,"abc"]))// === true
console.log(test(target, [0,1,2]))// === false
console.log(test(target, ["abc",5,4]))// === false
console.log(test(target, [2,4]))// === false
console.log(test(target, [])) // === false
console.log(test(target, [ "abc", "def", undefined ])) // === false
console.log(test([ 4, 5, 5, 6 ], [ 5, 5 ]))
CodePudding user response:
You can simply achieve this by just using Array.join()
and then check the index by using String.indexOf()
method.
As per the post, I am assuming you are searching only for the consecutive elements not a random one.
Live Demo :
const target = [1,2,3,4,5,"abc", "def"];
const search = [2,3,4];
const res = target.join().indexOf(search.join()) !== -1
console.log(res); // true