Rohitashv Singhal
Rohitashv Singhal

Reputation: 4557

How to get all possible intersections of multiple multidimensional arrays?

I have two arrays in PHP like this:

$array1 = array(array("1", "3", "4"), array("1", "4"));
$array2 = array(array("5", "4", "3", "2"), array("5", "3"));

Now I want to get all possible intersections of these two multidimensional arrays. Means I would get 4 arrays in total:

I can get the intersection from a onedimensional array using array_intersect(). But how can I get all possible intersections of multiple multidimensional arrays?

Upvotes: 1

Views: 569

Answers (2)

Rizier123
Rizier123

Reputation: 59681

Here we create an array containing all combinations of arrays, so we can later take the intersections of these arrays.

Array combinations

First we need to create all possible combinations of arrays. Which is:

carray 1 * carray 2 * ... * carray n

"c" Just means the count() of the arrays

So in your specific example it would be:

carray 1 * carray 2 => 2 * 2 => 4 combinations

Now we need to get all these combinations and put them into an array. For this we start with an empty $combinations array. Then we loop through all combinations which we have in the array and merge the next array into it, until we have the desired length of the combination, in this case the amount of arrays which we have.

So as an example:

Array with the elements (Empty array is '[]'):

[
    [[1, 3, 4], [1, 4]],     //array 1
    [[5, 4, 3, 2], [5, 3]],  //array 2
]

           1* combination array    2* new array     //↓new combinations
                    ↓                   ↓           //↓for the next iteration
                                                    │
array NAN*:

    Combinations:
                  - []                              │  -> []
                                                       │
array 1:            ┌──────────────────────────────────┘
                    │                       
    Combinations:   v                       
                  - []             + [1, 3, 4]      │  -> [[1, 3, 4]]  
                  - []             + [1, 4]         │  -> [[1, 4]]   
                                                       │
array 2:            ┌──────────────────────────────────┘
                    │                       
    Combinations:   v                       
                  - [[1, 3, 4]]    + [5, 4, 3, 2]   │  -> [[1, 3, 4], [5, 4, 3, 2]]
                  - [[1, 3, 4]]    + [5, 3]         │  -> [[1, 3, 4], [5, 3]]
                  - [[1, 4]]       + [5, 4, 3, 2]   │  -> [[1, 4], [5, 4, 3, 2]]
                  - [[1, 4]]       + [5, 3]         │  -> [[1, 4], [5, 3]] 
                                                    //↑ All combinations here

* NAN: not a number

So as you can see in the above example we now have all combinations with the length of the amount of all arrays which we have (4 combinations with a length of 2 elements).

The code to get the combinations as shown in the example above is:

//The for loop makes sure we get the desired length of each combination
//(The amount of arrays which we have. Here 2)
for ($count = 0, $length = count($data); $count < $length; $count++) {  

    $tmp = [];

    foreach ($combinations as $v1) {  //1* combinations array

        foreach ($data[$count] as $v2)  //2* new array
            $tmp[] = array_merge($v1, [$v2]);  //Creating new combinations

    }

    $combinations = $tmp;  //Assigning the new combinations for the next iteration

}

Which in your specific example generates this array:

Array
(
[0] => Array  //Combination 1
    (
        [0] => Array
            (
                [0] => 1
                [1] => 3
                [2] => 4
            )

        [1] => Array
            (
                [0] => 5
                [1] => 4
                [2] => 3
                [3] => 2
            )

    )

[1] => Array  //Combination 2
    (
        [0] => Array
            (
                [0] => 1
                [1] => 3
                [2] => 4
            )

        [1] => Array
            (
                [0] => 5
                [1] => 3
            )

    )

[2] => Array  //Combination 3
    (
        [0] => Array
            (
                [0] => 1
                [1] => 4
            )

        [1] => Array
            (
                [0] => 5
                [1] => 4
                [2] => 3
                [3] => 2
            )

    )

[3] => Array  //Combination 4
    (
        [0] => Array
            (
                [0] => 1
                [1] => 4
            )

        [1] => Array
            (
                [0] => 5
                [1] => 3
            )

    )

)

Array intersection

Now that we have all combinations we can just go through the combinations array with array_map() and get the array_intersect() of each combination. And since we don't know from how many arrays we want the intersection, we just use call_user_func_array(), e.g.

$intersections = array_map(function($v){
    //intersection of each combination, which we created
    return call_user_func_array("array_intersect", $v);
}, $combinations);

Full code:

<?php

    $array1 = [[1, 3, 4], [1, 4]];
    $array2 = [[5, 4, 3, 2], [5, 3]];


    function getIntersections($data = []) {
        $combinations = [[]];

        for ($count = 0, $length = count($data); $count < $length; $count++) {
            $tmp = [];
            foreach ($combinations as $v1) {
                foreach ($data[$count] as $v2)
                    $tmp[] = array_merge($v1, [$v2]);
            }
            $combinations = $tmp;
        }

        $intersections = array_map(function($v){
            return call_user_func_array("array_intersect", $v);
        }, $combinations);

        return $intersections;

    }

    $intersections = getIntersections([$array1, $array2]);
    print_r($intersections);

?>

output:

Array
(
    [0] => Array  //Intersection of: [1, 3, 4] && [5, 4, 3, 2]
        (
            [1] => 3
            [2] => 4
        )

    [1] => Array  //Intersection of: [1, 3, 4] && [5, 3]
        (
            [1] => 3
        )

    [2] => Array  //Intersection of: [1, 4] && [5, 4, 3, 2]
        (
            [1] => 4
        )

    [3] => Array  //Intersection of: [1, 4] && [5, 3]
        (
        )

)

Upvotes: 3

Rohitashv Singhal
Rohitashv Singhal

Reputation: 4557

This foreach is solving my problem

$array1= array(array("1","3","4"),array("1","4"));
$array2= array(array("5","4","3","2"),array("5","3"));
$result = array();
echo "<pre>";
foreach($array1 as $array1)
{
    foreach($array2 as $array3)
    {
        print_r($array3);
        $result[] = array_intersect($array1,$array3);
    }
}

print_r($result);

If You have better solution then plz improve it

Upvotes: 1

Related Questions