A simple implementation would be
return any(character in names_lower for character in n_val)
A naive guess at the complexity would be O(K*2*N)
where K
is the number of characters in names
and N
is the number of characters in n_val
. We need one "loop" for the call to lower*, one for the inner comprehension, and one for any
. Since any
is a built-in function and we're using a generator expression, I would expect it to be faster than your manual loop, but as always, profile to be sure.
To be clear, any
short-circuits, so that behaviour is preserved
Notes on Your Implementation
On using a set
: Your intuition to use a set to reduce the number of checks is a good one (you could add it to my form above, also), but it's a trade-off. In the case that the first element short circuits, the extra call to set is an additional N
steps to produce the set expression. In the case where you wind up checking each item, it will save you some time. It depends on your expected inputs. If n_val
was originally an iterable, you've lost that benefit and allocated all the memory up front. If you control the input to the function, why not just recommend it's called using lists that don't have duplicates (i.e., call set()
on its input), and leave the function general?
*
@Neopolitan pointed out that names_lower = names.lower()
should be called out of the loop, as your original implementation called it, else it may (will?) be called repeatedly in the generator expression