è possibile enumerare gli elementi del r esult set, cioè per ogni numero intero compreso tra 0 .... (numero di elementi) -1 puoi dire quale elemento ritornare (ad es.c'è un ordine naturale). Per il nostro esempio:
0 => array1[0], array2[0], array3[0]
1 => array1[0], array2[0], array3[1]
2 => array1[0], array2[1], array3[0]
7 => array1[1], array2[1], array3[1]
Tutto ciò che serve è un (intero) Indice n e una funzione che "traduce" l'indice all'elemento esimo del (naturale ordinato) insieme n. Dal momento che è sufficiente un numero intero per memorizzare lo stato corrente, il consumo di memoria non "esplode" quando si dispone di array molti/grandi. Come diceva chris nel suo commento, la velocità di scambio (quando si utilizzano set più piccoli) per un consumo di memoria ridotto. (Anche se penso che -la modo php è attueranno questa è anche una soluzione veloce ragionevole.)
$array1 = array('dog', 'cat');
$array2 = array('food', 'tooth');
$array3 = array('car', 'bike');
function foo($key /* , ... */) {
$params = func_get_args();
$rv = array();
$key = array_shift($params);
$i=count($params);
while(0 < $i--) {
array_unshift($rv, $params[$i][ $key % count($params[$i]) ]);
$key = (int)($key/count($params[$i]));
}
return $rv;
}
for($i=0; $i<8; $i++) {
$a = foo($i, $array1, $array2, $array3);
echo join(', ', $a), "\n";
}
È possibile utilizzare questo per implementare esempio un Iterator, un SeekableIterator o forse anche un ArrayAccess (e invertendo il controllo rispetto alle soluzioni ricorsive, quasi come un yield
in pitone o rubino)
<?php
$array1 = array('dog', 'cat', 'mouse', 'bird');
$array2 = array('food', 'tooth', 'brush', 'paste');
$array3 = array('car', 'bike', 'plane', 'shuttlecraft');
$f = new Foo($array1, $array2, $array3);
foreach($f as $e) {
echo join(', ', $e), "\n";
}
class Foo implements Iterator {
protected $data = null;
protected $limit = null;
protected $current = null;
public function __construct(/* ... */) {
$params = func_get_args();
// add parameter arrays in reverse order so we can use foreach() in current()
// could use array_reverse(), but you might want to check is_array() for each element.
$this->data = array();
foreach($params as $p) {
// <-- add: test is_array() for each $p -->
array_unshift($this->data, $p);
}
$this->current = 0;
// there are |arr1|*|arr2|...*|arrN| elements in the result set
$this->limit = array_product(array_map('count', $params));
}
public function current() {
/* this works like a baseX->baseY converter (e.g. dechex())
the only difference is that each "position" has its own number of elements/"digits"
*/
// <-- add: test this->valid() -->
$rv = array();
$key = $this->current;
foreach($this->data as $e) {
array_unshift($rv, $e[$key % count($e)]);
$key = (int)($key/count($e));
}
return $rv;
}
public function key() { return $this->current; }
public function next() { ++$this->current; }
public function rewind() { $this->current = 0; }
public function valid() { return $this->current < $this->limit; }
}
stampe
dog, food, car
dog, food, bike
dog, food, plane
dog, food, shuttlecraft
dog, tooth, car
dog, tooth, bike
[...]
bird, paste, bike
bird, paste, plane
bird, paste, shuttlecraft
(la sequenza sembra essere ok ;-))
Vuoi anche * cane *, * gatto *, * cibo per cani *, * dente di cane *, * cibo per gatti *, * dente di gatto * o solo le combinazioni di tutti gli array combinato? – Gordon
Solo la combinazione di tutti gli array per questo particolare problema, anche se sarebbe anche interessante da vedere. – hookedonwinter
Se si desidera poter lavorare con 100 matrici di dimensione 100, si avranno seri problemi di memoria che provano a generare effettivamente un array. La quantità di combinazioni è un numero davvero enorme. Questo è un prodotto cartesiano. È necessario un iteratore. Questo approccio scambia il tempo per lo spazio, è più lento, ma ti consente di rimanere entro i limiti di memoria. Vorrei pubblicare un link, ma sarebbe sul sito web di un membro attivo qui. Se non viene da solo e risponde, posterò il link. Ma altrimenti non voglio rubare la sua gloria. – goat