PHP数组多属性进行排列组合

抽象一下需求:

在构建某个对象时,它拥有多个属性,每个属性拥有多个可选的值,需要穷举出每个属性不同的选择组合构建出的不同对象,比如:

输入参数:

$arr = [
    'Name' => ['Jack', 'Lily', 'Martin'],
    'Age' => ['18', '12'],
    'Gender' => ['male', 'female'],
    'Address' => ['Alexander', 'Huston', 'NewYork'],
];

从每个属性中取一个值,根据排列组合计算知道可以得到 36 个不同的人。

期望结果:

篇幅原因,中间省略掉。

array (
  0 =>
  array (
    'Name' => 'Jack',
    'Age' => '18',
    'Gender' => 'male',
    'Address' => 'Alexander',
  ),
  1 =>
  array (
    'Name' => 'Jack',
    'Age' => '18',
    'Gender' => 'male',
    'Address' => 'Huston',
  ),

  ...

  34 =>
  array (
    'Name' => 'Martin',
    'Age' => '12',
    'Gender' => 'female',
    'Address' => 'Huston',
  ),
  35 =>
  array (
    'Name' => 'Martin',
    'Age' => '12',
    'Gender' => 'female',
    'Address' => 'NewYork',
  ),
)

实现代码:

/**
 * 排列组合
 * @param $arr
 * @return array
 */
function pac($arr): array
{

    if (empty($arr)) {
        return [];
    }

    $n = count($arr);   // 维度数量
    $count = 1;         // 结果总数
    $size = [];         // 每个属性的可选值个数
    $visit = [];        // 每个属性当前访问到的位置(下标)
    $keyIndex = [];     // 保存每个属性的key
    $res = [];          // 保存结果

    // 初始化
    $i = 0;
    foreach ($arr as $key => $values) {
        $size[$i] = count($values);
        $visit[$i] = 0;
        $count *= count($values);
        $keyIndex[$i] = $key;
        $i ++;
    }

    $m = 0;
    $temp = [];
    while (true) {

        for ( $i = 0; $i < $n; $i++ ) {
            // 取当前位置的下一个位置记录到最终的数组中
            $temp[$m][$i] = $visit[$i] + 1;
        }

        $m ++;

        for ( $i = $n - 1; $i >= 0; $i-- ) {
            // 取的是可选值的最后一个值时,重置位置记录,下一个组合从0位置开始
            if ($visit[$i] == $size[$i] - 1) {
                $visit[$i] = 0;
            } else {
            // 当前属性未取完
                break;
            }
        }

        // 当所有属性的值都取完了,经过最后一次$i--, $i 值变为 -1,循环完成
        if ($i < 0) {
            break;
        }
        // 位置后移
        $visit[$i] ++;

    }

    for ($i = 0; $i < $count; $i ++) {
        for ($j = 0; $j < $n; $j ++) {
            $res[$i][$keyIndex[$j]] = $arr[$keyIndex[$j]][$temp[$i][$j]-1];
        }
    }

    return $res;

}


如果需求是想要从多个元素中取n个出来,得到多种不同的结果,如果可选元素集合为['a', 'b','c'],n为2,这样传值:

$arr = [
    ['a', 'b','c'],
    ['a', 'b','c'],
];

得到的结果(部分):

array (
  0 =>
  array (
    0 => 'a',
    1 => 'a',
  ),
  1 =>
  array (
    0 => 'a',
    1 => 'b',
  ),

  ...

  7 =>
  array (
    0 => 'c',
    1 => 'b',
  ),
  8 =>
  array (
    0 => 'c',
    1 => 'c',
  ),
)
PHP数组多属性进行排列组合

原文链接:https://beltxman.com/3770.html,若无特殊说明本站内容为行星带原创,未经同意禁止转载!

更多精彩,敬请关注本博微信公众号:hsu1943

发表评论

电子邮件地址不会被公开。 必填项已用*标注

Scroll to top