Is there a name for this for loop pattern and if so is there a better way to write it?

Viewed 115

Here is an example function with the pattern I am referring to:

fn check_sub_listiness<T: PartialEq>(big_list: &[T], small_list: &[T]) -> bool {
    for poss_sublist in big_list.windows(small_list.len()) {
        if poss_sublist == small_list {
            return true;
        }
    }
    false
}

This code takes a big list and a small list and returns whether the small list is a sublist of the big list. I wrote it as part of an Exercism exercise I was doing. I find myself using this pattern alot, where I loop through some options, check for a condition, and return true if I find it or false if I make it to the end of the loop without finding what I was looking for. Is there a name for this? More importantly, is there a better more semantic way to write it (in Rust or any other language).

2 Answers

Iterating until success is like .find() but if you're only interested in a true/false result you can use .any(), which does exactly what you're asking for.

Tests if any element of the iterator matches a predicate.

any() takes a closure that returns true or false. It applies this closure to each element of the iterator, and if any of them return true, then so does any(). If they all return false, it returns false.

any() is short-circuiting; in other words, it will stop processing as soon as it finds a true, given that no matter what else happens, the result will also be true.

An empty iterator returns false.

So your loop can be written like this:

fn check_sub_listiness<T: PartialEq>(big_list: &[T], small_list: &[T]) -> bool {
    big_list.windows(small_list.len()).any(|poss_sublist| {
        poss_sublist == small_list
    })
}

The loop you provided is an instance of exhaustive search, I would probably call it that. Hence the call for a more efficient loop, but I'm also sceptical if that's possible here. If the big list is sorted, you coud work with binary search.

Related