Combinations of X elements into 1, 2, 3, 4, … X sub-sub-arrays

谁说胖子不能爱 提交于 2019-12-14 04:14:06

问题


I have an array that looks like this: [0, 1, 2, 3, 4, 5, ...]

I need a function that will give me an array like this:

[
[[0, 1, 2, 3, 4, 5]],  
[[0, 1, 2, 3, 4], [ 5 ]], 
[[0, 1, 2, 3], [ 4, 5 ]], 
[[0, 1, 2], [ 3, 4, 5 ]], 
...
[[0, 1, 2], [ 3, 4 ], [ 5 ]],
...
[[ 0 ], [ 1 ], [ 2 ], [ 3 ], [ 4 ], [ 5 ]]
]

Of course this output is only for 6 elements.
If you look at the 2nd, 3rd and 4th line of the output array, it's some sort of combination into 2 sub-arrays.
If you look at the 6th line of the output array, it becomes into 3 sub-arrays.
In the last line every element should be alone in its own sub-array.

I saw the examples on this page and I tried the functions but mine is a little different because the order of the elements need to be respected. This means that regardless of where the brackets are, you should see 1 2 3 4 5 6 on each line.

Also, the functions in the previously mentioned page will give me an array including all the sub-arrays:
[[x,x],[x],[x],[xxx]] I can't use this.

What I need is this format:

[  
[ [ 1 , 2 , 3 ] ] ,  
[ [ 1 , 2 ] , [ 3 ] ] ,  
[ [ 1 ] , [ 2 , 3 ] ] ,  
[ [ 1 ] , [ 2 ] , [ 3 ] ]  
]

I am a beginner, please someone give me a hint on how to do this!


回答1:


I've just developed a very special way to achieve what you're looking for (traversing a binary tree using binary labels! I don't know if it already exists!!) It's extremely fast and doesn't use recursion :)

<?php
function getSpecialSubsets($in) {
    $in = array_reverse($in);
    $n = count($in);

    $out = array();
    // for every possible route
    for($i = 0; $i<pow(2, $n-1); $i++) {
        $out[$i] = array(array());

        // for every value in the input array
        for($j=$n-1; $j>=0; $j--) {
            $val = $in[$j];
            if(($i >> $j) & 1)
                $out[$i][] = array($val);
            else $out[$i][count($out[$i])-1][] = $val;
        }
    }

    return $out;
}

$subsets = getSpecialSubsets([1, 2, 3, 4]);

// for demonstration purposes only!!
echo "<pre>";
echo preg_replace('~\]\],~', "]],\n", json_encode($subsets));
echo "</pre>";
?>



回答2:


This took me hours to be produced!!

You're right, your question is wrongly set as duplicate. However, In that question what you wanted is involved to get all the Partitions of the set instead of what you wanted here (here you wanted a subset of that set.) In either of cases, you can use the following to get the desired output, just replace the name of the desired function in the marked line to whatever you want (I mean you may also change it to getSpecialSubsets() presented above.

As you call tell, the desired principal function of getVerySpecialSubsets() also has the favorable arguments of $level_min and $level_max :)

<?php
function allPermutations($InArray, $InProcessedArray = array())
{
    $ReturnArray = array();
    foreach($InArray as $Key=>$value)
    {
        $CopyArray = $InProcessedArray;
        $CopyArray[$Key] = $value;
        $TempArray = array_diff_key($InArray, $CopyArray);

        if (count($TempArray) == 0)
            $ReturnArray[] = array_values($CopyArray);
        else
            $ReturnArray = array_merge($ReturnArray, allPermutations($TempArray, $CopyArray));
    }
    return $ReturnArray;
}

function powerSet($in,$minLength = 1) { 
   $count = count($in); 
   $members = pow(2,$count); 
   $return = array(); 
   for ($i = 0; $i < $members; $i++) { 
      $b = sprintf("%0".$count."b",$i); 
      $out = array(); 
      for ($j = 0; $j < $count; $j++) { 
         if ($b{$j} == '1') $out[] = $in[$j]; 
      } 
      if (count($out) >= $minLength) { 
         $return[] = $out; 
      } 
   } 
   return $return; 
}

function getAllPartitionsOfSet($in) {
    $arr = powerSet(powerSet($in));

    $out = array();
    foreach($arr as $combination) {
        $a = array();
        foreach($combination as $_arr)
            foreach($_arr as $v)
                $a[] = $v;

        // check if $a has duplicates
        // (i.e: the intersection of subsets in $combination is void)
        if(count($a) !== count(array_unique($a)))
            continue;

        // check if there's no difference between $a and $in.
        // (i.e: the union of subsets in $combination is equal to $a)
        if(!empty(array_diff($a, $in)) || !empty(array_diff($in, $a)))
            continue;

        $out[] = $combination;
    }
    return $out;
}

function getVerySpecialSubsets($_in, $level_min = 1, $level_max = 0) {
    $in = array_reverse($_in);
    $n = count($in);

    $level_min = $level_min>0 ? $level_min : 1;
    $level_max = $level_max>0 ? $level_max : $n;

    $allPartitions = getAllPartitionsOfSet($_in); //* marked!
    $out = array();

    foreach($allPartitions as $partition) {
        $levels_count = count($partition);
        if($levels_count>$level_max || $levels_count<$level_min)
            continue;

        // add the permutations of the arrays
        for($i=0; $i<count($partition); $i++) {
            $per = allPermutations($partition[$i]);
            if(count($per)==1)
                continue;

            // combine the permutation with the rest of array
            $first_item = true;
            foreach($per as $_per) {
                $arr = array();
                for($j=0; $j<count($partition); $j++)
                    $arr[] = ($j==$i) ? $_per : $partition[$j];
                $out[] = $arr;
            }
        }
    }

    // last singles
    if($n<=$level_max && $n>=$level_min) {
        $arr_last = array();
        for($k=count($in)-1; $k>=0; $k--)
            $arr_last[] = array($in[$k]);
        $out[] = $arr_last;
    }

    return array_values(array_unique($out, SORT_REGULAR));
}

$subsets = getVerySpecialSubsets([0, 1, 2]);

// for demonstration purposes only!!
echo '<pre>';
echo preg_replace('~\]\],~', "]],\n", json_encode($subsets));
echo '</pre>';
?>


来源:https://stackoverflow.com/questions/30678450/combinations-of-x-elements-into-1-2-3-4-x-sub-sub-arrays

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!