Need help with nested lambda exptression

I have here a solution of an exercise from codewars.com which I don't understand.

The exercise explination is:
Given two arrays of strings a1 and a2 return a sorted array r in lexicographical order of the strings of a1 which are substrings of strings of a2.

#Example 1: a1 = ["arp", "live", "strong"]

a2 = ["lively", "alive", "harp", "sharp", "armstrong"]

returns ["arp", "live", "strong"]

#Example 2: a1 = ["tarp", "mice", "bull"]

a2 = ["lively", "alive", "harp", "sharp", "armstrong"]

returns []

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <algorithm>
#include <string>
#include <vector>
#include <iostream>

class WhichAreIn
{
public:
    static std::vector<std::string> inArray(
            std::vector<std::string> &array1,
            std::vector<std::string> &array2
    )
    {
        std::vector<std::string> results;
        
        std::copy_if( array1.begin( ), array1.end( ), std::back_inserter( results ),
            [&](const std::string &item1) {
                return std::any_of( array2.begin( ), array2.end( ), 
                    [&](const std::string &item2) {
                        return item2.find( item1 ) != std::string::npos;
                    } 
                );
            } 
        );
        
        std::sort( results.begin( ), results.end( ) );
        
        return results;
    }
};
int main()
{
    std::vector<std::string> subs { "strong", "is", "live",};
    std::vector<std::string> arr { "lively", "alive", "harp", "sharp", "armstrong" };
    std::vector<std::string> solution = WhichAreIn::inArray( subs, arr);
    
    for( auto & word : solution) std::cout << word << ", ";
    
}

Can someone please WhichAreIn::inArray() explain? Especial what's going on in the nested lambda I don't understand.
Do it in pieces:

1
2
3
4
5
 std::copy_if( array1.begin( ), array1.end( ), std::back_inserter( results ),
           some_lambda_function
                );
            } 
        );


This says for the range of all elements from the start of array1 to the end of array1, copy the element into results IF some_lambda_function returns "true".

Now look at the function. When will it return true?

1
2
3
 [&](const std::string &item1) {
                return std::any_of( array2.begin( ), array2.end( ), 
                    another_lambda_function 


This function will return true if, for any_of the elements in array2 , another_lambda_function returns true. Each element of array2 will be examined in turn, and if another_lambda_function says "true" for any of them, this function returns true.

So what does another_lambda_function do?

1
2
3
[&](const std::string &item2) {
                        return item2.find( item1 ) != std::string::npos;
                    } 


item2 is a string - the element of array2 under consideration. item1 is the element of array1 under consideration. So this function returns true if item1 is found inside item2. This function returns true if the string from array2 under consideration contains the string from array1.

So from inside out, the second lambda says "return true if this string from array1 is found inside any string from array2", and the first lambda says "if the second lambda says 'true', copy this element of array1 to results", and the first lambda is being run over all elements of array1.
Last edited on
Thank you Repeater! (I got a knot at my cerebral gyri ;)
Topic archived. No new replies allowed.