strings_to_check = ["a", "b", "c"]
test_arrrays = [ [ "a", "c", "e", "g"], [ "v", "x", "y", "z"] ]
What is the right way to check if each array in test_arrays
contains any
of the strings in strings_to_check
array - ie. a, b or c
I could do the following, but it has its downside that even if one of the strings is present, it still check's for the rest.
for(let i = 0; i < test_arrrays.length; i++){
for(let j = 0; j < strings_to_check.length; j++){
if(test_arrrays[i].indexOf(strings_to_check[j]) > -1) {
console.log("matched");
}
}
}
4 Answers 4
This can be much more simply done with higher order functions, instead of devolving to using for loops and a slew of indices.
We want to see if all
test_arrrays
elements meet some criteria, so we know we should useevery
:test_arrrays.every(/* some criteria */);
Now we just have to find out what that criteria is. "contains any of the strings in strings_to_check" Sounds like we need to use
some
ontest_array
, to find out if any of its strings are contained instrings_to_check
. So our "criteria" will be:test_arrray => test_arrray.some(s => strings_to_check_set.includes(s))
putting it together, we get:
test_arrrays.every( test_arrray => test_arrray.some(s => strings_to_check_set.includes(s)) )
includes
has linear time complexity, so we can improve this algorithm by using aSet
, and replacingincludes
withhas
, which has constant time complexity., to obtain this final result:strings_to_check = ["a", "b", "c"] test_arrrays = [ [ "a", "c", "e", "g"], [ "v", "x", "y", "z"] ] strings_to_check_set = new Set(strings_to_check) test_arrrays.every(test_arrray => test_arrray.some(s => strings_to_check_set.has(s)) )
4 Comments
some
function with every
, because as for now, it will return true
even if only one array fulfills the condition (contains any item from strings_to_check
array).Assuming that you want to check if every array from test_arrays
contains at least one element from the strings_to_check
array, you could use mix of Array#every
and Array#some
functions.
var strings_to_check = ["a", "b", "c"],
test_arrrays = [ [ "a", "c", "e", "g"], [ "v", "x", "y", "z"] ],
res = test_arrrays.every(v => v.some(c => strings_to_check.indexOf(c) > -1));
console.log(res);
Comments
If you have multiple test_arrrays
, it makes sense to convert the strings_to_check
into a Set
for constant time lookup. The overall time complexity then reduces from O(m n) to O(m + n log n) where n is the number of elements in strings_to_check
and m is the total number of elements in all test_arrrays
and O(n log n) is the Set
setup time.
A generic check
function would then look as follows:
// Check if each haystack contains at least one needle:
function check(needles, haystacks) {
needles = new Set(needles);
return haystacks.every(haystack => haystack.some(element => needles.has(element)));
}
// Example:
console.log(check(
["a", "b", "c"],
[["a", "c", "e", "g"], ["v", "x", "y", "z"]]
));
Comments
If you only need to match one string just add break
just like this :
for(/*loop settings*/){
/*some code*/
for(/*loop settings*/){
/*some code*/
if(/*some conditional statement*/){
/*handling stuff*/
break;
}
}
}
let test = test_arrays.every(a => a.some(s => strings_to_check.includes(s)));
.