Вы можете перечислить элементы набора результатов, то есть для каждого целого числа от 0 .... (количество элементов) -1, вы можете указать, какой элемент возвращать (т. Е. Существует естественный порядок). Для данного примера:
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]
Все, что вам нужно, - это (целочисленный) индекс n и функция, которая «переводит» индекс в n -й элемент набора (в естественном порядке). Поскольку вам нужно только целое число для хранения текущего состояния, потребление памяти не «взрывается», когда у вас много / большие массивы. Как сказал Крис в своем комментарии, вы торгуете скоростью (при использовании меньших наборов) для низкого потребления памяти. (Хотя я думаю - способ реализации php - это тоже разумное быстрое решение.)
$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";
}
Вы можете использовать это, например, для реализации. Итератор , SeekableIterator или, может быть, даже ArrayAccess (и, таким образом, инвертирующий управление по сравнению с рекурсивными решениями, почти как yield
в питоне или рубине)
<?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; }
}
печать
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
(последовательность вроде бы в порядке ;-))