Hier ist eine nicht-rekursive Version, die ebenfalls
/**
* Generates all the possible unique N-tuples from an array of N arrays of integers
*
* @param array $input
* @return array
*/
function generateCombinations(array &$input) {
// since the example results included [1, 3, null] I have assumed that
// null is a possible value of each set.
$sets = [];
foreach($input as $set) {
if(!in_array(null, $set)) {
$set[] = null;
}
$sets[] = $set;
}
// by working on the iterators of each array this loop
// linearizes the entire set of possible combinations
// and iterates it (skipping as many as it can).
$output = [];
$setCount = count($sets);
while(current($sets[0]) !== false) {
$testCombo = [];
for($setIdx = 0; $setIdx < $setCount; $setIdx++) {
if(!in_array(current($sets[$setIdx]), $testCombo)) {
$testCombo[] = current($sets[$setIdx]);
}
else {
// when a combination is thrown out as duplicate
// iterate to skip any other combo's that would also
// contain that duplicate
iterateSets($sets, $setIdx);
break;
}
}
// if there were no duplicates add it to the output and iterate
if(count($testCombo) == $setCount) {
$output[] = $testCombo;
iterateSets($sets, $setCount - 1);
}
}
return $output;
}
/**
* Iterates to the next potentially valid combination. I think of
* this like doing long-hand addition. Add 1 and carry is akin to
* next and reset.
*
* @param array $sets
* @param $index
*/
function iterateSets(array &$sets, $index) {
// reset iterators of all sets past the current one to skip
// combos that cannot be valid
for($i = $index + 1, $ic = count($sets); $i < $ic; $i++) {
reset($sets[$i]);
}
// always move one on current set
next($sets[$index]);
while($index > 0 && current($sets[$index]) === false) {
// wrap if current set is at the end
reset($sets[$index]);
$index--;
// move one for the preceding set
next($sets[$index]);
// then repeat
}
}
Das resultierende Array optimiert ist:
[
[1,2,3]
[1,2,null]
[1,3,null]
[1,4,3]
[1,4,null]
[1,null,3]
[2,3,1]
[2,3,null]
[2,4,1]
[2,4,3]
[2,4,null]
[2,null,1]
[2,null,3]
[4,2,1]
[4,2,3]
[4,2,null]
[4,3,1]
[4,3,null]
[4,null,1]
[4,null,3]
[5,2,1]
[5,2,3]
[5,2,null]
[5,3,1]
[5,3,null]
[5,4,1]
[5,4,3]
[5,4,null]
[5,null,1]
[5,null,3]
[null,2,1]
[null,2,3]
[null,3,1]
[null,4,1]
[null,4,3]
]
Ich finde Ihre Beispielausgabe ein wenig verwirrend - können Sie eine * full * Beispielausgabe bereitstellen? –
Ich bin auch ein bisschen verwirrt mit Ihrer erwarteten Ausgabe. Bitte geben Sie alle Kombinationen an, die Sie für die Beispieldaten erwarten. Wie ich es jetzt sehe, möchten Sie nur eine Zahl von jedem UnterArray auswählen, aber keine doppelten Werte. Aber du willst auch, dass jede Kombination die Länge aller SubArrays ist. Sie scheinen auch NULL als "Füller" zu verwenden, um zu Ihrer Kombinationslänge zu gelangen. Also betrachtest du es als wäre es ein Wert in jedem subArray ?! Also wäre eine Kombination wie: '[1, 2, NULL, NULL]' möglich, wenn die letzten zwei SubArrays nur 1 und 2 enthalten? – Rizier123
Und wenn Sie 3 SubArrays haben, ist '[NULL, NULL, NULL]' eine mögliche Kombination? Oder ist "NULL" nur ein Füller? Auch wenn Sie die Schlüssel in Ihrer Ausgabe explizit anzeigen, möchten Sie die Schlüssel der SubArrays verwenden? Oder sind es einfach die gleichen? – Rizier123