如何获得多个多维数组的所有可能交集?

Posted

技术标签:

【中文标题】如何获得多个多维数组的所有可能交集?【英文标题】:How to get all possible intersections of multiple multidimensional arrays? 【发布时间】:2015-12-12 12:27:18 【问题描述】:

我在 php 中有两个这样的数组:

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

现在我想得到这两个多维数组的所有可能的交集。意味着我总共会得到 4 个数组:

$array1[0] & $array2[0] $array1[1] & $array2[0] $array1[0] & $array2[1] $array1[1] & $array2[1]

我可以使用array_intersect() 从一维数组中获取交集。但是我怎样才能得到多个多维数组的所有可能的交集呢?

【问题讨论】:

【参考方案1】:

这里我们创建了一个包含所有数组组合的数组,因此我们以后可以取这些数组的交集。

数组组合

首先我们需要创建所有可能的数组组合。即:

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

"c" 只表示数组的count()

因此,在您的具体示例中,它将是:

c数组 1 * c数组 2 => 2 * 2 => 4 个组合

现在我们需要获取所有这些组合并将它们放入一个数组中。为此,我们从一个空的 $combinations 数组开始。然后我们循环遍历数组中的所有组合并将下一个数组合并到其中,直到我们获得所需的组合长度,在本例中为我们拥有的数组数量。

举个例子:

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:不是数字

正如您在上面的示例中看到的那样,我们现在拥有所有组合,其长度与我们拥有的所有数组的数量相同(4 个组合,长度为 2 个元素)。

如上例中获取组合的代码为:

//for循环确保我们得到每个组合所需的长度
//(我们拥有的数组数量。这里是2)
for ($count = 0, $length = count($data); $count //1* 组合数组

        foreach ($data[$count] as $v2) //2* 新数组
            $tmp[] = array_merge($v1, [$v2]); //创建新的组合

    

    $组合 = $tmp; //为下一次迭代分配新的组合


在您的具体示例中生成此数组:

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_map() 遍历组合数组并获得每个组合的 array_intersect()。而且由于我们不知道需要多少个数组进行交集,所以我们只使用call_user_func_array(),例如

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

完整代码:

<?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);

?>

输出:

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]
        (
        )

)

【讨论】:

【参考方案2】:

这个foreach 正在解决我的问题

$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);

如果你有更好的解决方案,请改进它

【讨论】:

以上是关于如何获得多个多维数组的所有可能交集?的主要内容,如果未能解决你的问题,请参考以下文章

在 PHP 中执行数组交集时如何保留多维数组信息?

PHP确定多维数组中数组之间的交集

创建所有可能的三元组的多维数组

多维关联数组交集php

在PHP中获取多维数组的交集

连接两个单维列表以获得一个多维列表