用PHP关联数组求笛卡儿积

假设我有一个数组,如下所示:

Array(
    [arm] => Array
        (
            [0] => A            [1] => B            [2] => C        )
    [gender] => Array
        (
            [0] => Female
            [1] => Male
        )
    [location] => Array
        (
            [0] => Vancouver
            [1] => Calgary
        ))

如何在保留外部关联数组的键并在内部数组中使用它们的同时,找到笛卡儿积?算法的结果应该是:

Array(
    [0] => Array
        (
            [arm] => A            [gender] => Female
            [location] => Vancouver
        )

    [1] => Array
        (
            [arm] => A            [gender] => Female
            [location] => Calgary
        )

    [2] => Array
        (
            [arm] => A            [gender] => Male
            [location] => Vancouver
        )...etc.

我已经查阅了很多笛卡尔积算法,但我仍然停留在如何保存关联键的细节上。我目前使用的算法只给出数字索引:

    $result = array();
    foreach ($map as $a) {
        if (empty($result)) {
            $result = $a;
            continue;
        }
        $res = array();
        foreach ($result as $r) {
            foreach ($a as $v) {
                $res[] = array_merge((array)$r, (array)$v);
            }
        }
        $result = $res;
    }

    print_r($result);

任何帮助都将不胜感激。

用PHP关联数组求笛卡儿积

拉丁的传说
浏览 599回答 3
3回答

ibeautiful

我能想到的是:function&nbsp;inject($elem,&nbsp;$array)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;array_map(function&nbsp;($n)&nbsp;use&nbsp;($elem)&nbsp;{&nbsp;return&nbsp;array_merge((array)$elem,&nbsp;(array)$n);&nbsp;},&nbsp;$array);}function&nbsp;zip($array1,&nbsp;$array2)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;array_reduce($array1,&nbsp;function&nbsp;($v,&nbsp;$n)&nbsp;use&nbsp;($array2)&nbsp;{&nbsp;return&nbsp;array_merge($v,&nbsp;inject($n,&nbsp;$array2));&nbsp;&nbsp;},&nbsp;array());} &nbsp;&nbsp;&nbsp;&nbsp;function&nbsp;cartesian_product($array)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;$keys&nbsp;=&nbsp;array_keys($array); &nbsp;&nbsp;&nbsp;&nbsp;$prod&nbsp;=&nbsp;array_shift($array); &nbsp;&nbsp;&nbsp;&nbsp;$prod&nbsp;=&nbsp;array_reduce($array,&nbsp;'zip',&nbsp;$prod); &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;array_map(function&nbsp;($n)&nbsp;use&nbsp;($keys)&nbsp;{&nbsp;return&nbsp;array_combine($keys,&nbsp;$n);&nbsp;},&nbsp;$prod);}(下面使用伪数组/列表/字典表示法,因为PHP对于这类事情太冗长了。)这个inject函数变换a, [b]进[(a,b)],即它向数组的每个值注入一个值,返回一个数组。不管是不是a或b已经是一个数组了,它将始终返回一个二维数组。inject('a',&nbsp;['foo',&nbsp;'bar']) &nbsp;&nbsp;&nbsp;&nbsp;=>&nbsp;&nbsp;[('a',&nbsp;'foo'),&nbsp;('b',&nbsp;'bar')]这个zip函数应用inject函数到数组中的每个元素。zip(['a',&nbsp;'b'],&nbsp;['foo',&nbsp;'bar']) &nbsp;&nbsp;&nbsp;&nbsp;=>&nbsp;&nbsp;[('a',&nbsp;'foo'),&nbsp;('a',&nbsp;'bar'),&nbsp;('b',&nbsp;'foo'),&nbsp;('b',&nbsp;'bar')]请注意,这实际上产生了笛卡尔积,因此zip有点用词不当。简单地将此函数应用于数据集中的所有元素,就可以得到任意长度数组的笛卡儿积。zip(zip(['a',&nbsp;'b'],&nbsp;['foo',&nbsp;'bar']),&nbsp;['42',&nbsp;'76']) &nbsp;&nbsp;&nbsp;&nbsp;=>&nbsp;&nbsp;[('a',&nbsp;'foo',&nbsp;'42'),&nbsp;('a',&nbsp;'foo',&nbsp;'76'),&nbsp;('a',&nbsp;'bar',&nbsp;'42'),&nbsp;…]这不包含键,但是由于元素在结果集中都是按顺序排列的,所以您可以简单地将键重新注入结果。array_combine(['key1',&nbsp;'key2',&nbsp;'key3'],&nbsp;['a',&nbsp;'foo',&nbsp;'42']) &nbsp;&nbsp;&nbsp;&nbsp;=>&nbsp;&nbsp;[&nbsp;key1&nbsp;:&nbsp;'a',&nbsp;key2&nbsp;:&nbsp;'foo',&nbsp;key3&nbsp;:&nbsp;'42'&nbsp;]将其应用于产品中的所有元素,将得到所需的结果。如果您愿意,可以将上述三个函数折叠成一个长语句(这也可以清除错误的名称)。对于PHP<=5.2没有匿名函数的“展开”版本如下所示:function&nbsp;inject($elem,&nbsp;$array)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;$elem&nbsp;=&nbsp;(array)$elem; &nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;($array&nbsp;as&nbsp;&$a)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$a&nbsp;=&nbsp;array_merge($elem,&nbsp;(array)$a); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$array;}function&nbsp;zip($array1,&nbsp;$array2)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;$prod&nbsp;=&nbsp;array(); &nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;($array1&nbsp;as&nbsp;$a)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$prod&nbsp;=&nbsp;array_merge($prod,&nbsp;inject($a,&nbsp;$array2)); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$prod;}function&nbsp;cartesian_product($array)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;$keys&nbsp;=&nbsp;array_keys($array); &nbsp;&nbsp;&nbsp;&nbsp;$prod&nbsp;=&nbsp;array_shift($array); &nbsp;&nbsp;&nbsp;&nbsp;$prod&nbsp;=&nbsp;array_reduce($array,&nbsp;'zip',&nbsp;$prod); &nbsp;&nbsp;&nbsp;&nbsp;foreach&nbsp;($prod&nbsp;as&nbsp;&$a)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$a&nbsp;=&nbsp;array_combine($keys,&nbsp;$a); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;$prod;}
打开App,查看更多内容
随时随地看视频慕课网APP