分享

php多维数组的排列组合(商品多规格或多套餐等)算法

方法一:

<?php
/**
 * 返回给的数组的所有组合
 * @email kavtong@163.com
 * @param array $orignal 多维数组
 *      $orignal = array(
 *              array(1,2,3),
 *              array(4,5,6),
 *              array(7,8,9),
 *      );
 * @return array(
 *              array(1,4,7),
 *              array(1,4,8),
 *              array(1,4,9),
 *              ...
 *              array(3,6,7),
 *              array(3,6,8),
 *              array(3,6,9),
 *          );
 *  数组元素共: 3*3*3 = 27个
 */
function getPermutation(array $orignal = array()){
    // 排除非数组的参数
    if(!is_array($orignal)){
        return [];
    }
    
    // 排除空数组
    if(empty($orignal)){
        return [];
    }

    // 排除只有一个元素的数组
    if(count($orignal) < 2){
        // 返回的目标数组
        $targetTmp = array_shift($orignal);
        // 返回结果集
        return is_array($targetTmp)?$targetTmp:[];
    }
    // 构建目标数组
    $target = array_shift($orignal);
    // 目标数组第一个元素格式化为数组
    $target = is_array($target)?$target:[];
    // 下一个需要处理的数组
    $tmp = array_shift($orignal);
    // 非正常数据标识
    $invalideParam = false;
    // 数组且不为空
    while(is_array($tmp) && !empty($tmp)){
        // 验证参数是否是一维数组
        if(count($tmp) <> count($tmp,COUNT_RECURSIVE)){
            $invalideParam = true;
            break;
        }
        /**
         * 原始数组的循环
         * array(
         *      0 =>1,
         *      1 =>2,
         *      2 =>3,
         * );
         */
        // 目标数组的临时变量
        $targetTmp = array();
        foreach($target as $value){
            foreach($tmp as $v){
                // 临时数组变量
                $targetTmp[] = array_merge((array)$value,[$v]);
            }
        }
        // 原始数组的替换
        $target = $targetTmp;
        // 移动数组的下一个元素
        $tmp = array_shift($orignal);
    }
    // 存在非一维数组项
    if($invalideParam){
        return [];
    }
    // 返回结果集
    return is_array($target)?$target:[];
}

 

方法二,使用递归函数创建每个不同子阵列的所有组合:

function combinations($array) {
    if (count($array) == 1) return reset($array);
    $result = array();
    foreach (reset($array) as $value) {
        foreach (combinations(array_slice($array, 1)) as $comb) {
            $result[] = array_merge($value, $comb);
        }
    }
    return $result;
}
$input = '{"1":[["Red"],["Green"],["Blue"],["Purple"]],"2":[["S"],["M"],["L"]],"3":[["Wool"],["Cotton"]]}';
$arr = json_decode($input, true);
$combs = combinations($arr);

返回如下数组:

Array
(
    [0] => Array
        (
            [0] => Red
            [1] => S
            [2] => Wool
        )
    [1] => Array
        (
            [0] => Red
            [1] => S
            [2] => Cotton
        )
    [2] => Array
        (
            [0] => Red
            [1] => M
            [2] => Wool
        )
    ...
    [22] => Array
        (
            [0] => Purple
            [1] => L
            [2] => Wool
        )
    [23] => Array
        (
            [0] => Purple
            [1] => L
            [2] => Cotton
        )
)

要获得逗号分隔字符串的列表,可以使用array_mapimplode应用于这些数组,例如:

$csv = array_map(function ($a) { return implode(',', $a); }, $combs);

这将生成如下数组:

Array
(
    [0] => Red,S,Wool
    [1] => Red,S,Cotton
    [2] => Red,M,Wool
    [3] => Red,M,Cotton
    [4] => Red,L,Wool
    [5] => Red,L,Cotton
    [6] => Green,S,Wool
    [7] => Green,S,Cotton
    [8] => Green,M,Wool
    [9] => Green,M,Cotton
    [10] => Green,L,Wool
    [11] => Green,L,Cotton
    [12] => Blue,S,Wool
    [13] => Blue,S,Cotton
    [14] => Blue,M,Wool
    [15] => Blue,M,Cotton
    [16] => Blue,L,Wool
    [17] => Blue,L,Cotton
    [18] => Purple,S,Wool
    [19] => Purple,S,Cotton
    [20] => Purple,M,Wool
    [21] => Purple,M,Cotton
    [22] => Purple,L,Wool
    [23] => Purple,L,Cotton
)

—转发自网络。