1
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");
      }
  }
}
1
  • 1
    let test = test_arrays.every(a => a.some(s => strings_to_check.includes(s)));. Commented May 1, 2017 at 17:51

4 Answers 4

2

This can be much more simply done with higher order functions, instead of devolving to using for loops and a slew of indices.

  1. We want to see if all test_arrrays elements meet some criteria, so we know we should use every:

    test_arrrays.every(/* some criteria */);
    
  2. 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 on test_array, to find out if any of its strings are contained in strings_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))
      )
    
  3. includes has linear time complexity, so we can improve this algorithm by using a Set, and replacing includes with has, 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))
    )
    
Sign up to request clarification or add additional context in comments.

4 Comments

Unfortunately your function returns a wrong result.
@Kinduser username checks out. Does it? What was your test case?
I guess you should replace your first 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).
@Kinduser Oh, I misunderstood the question. Fixing it now
1

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

1

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

0

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;
    }
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.