问题
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