How to generate combinations of elements in multiple arrays?

This is my first question :)

I have an array with the number of children of the array, each of which has unique values ​​and would like to get all possible unique combinations of these values.

The number of arrays is known, but may vary over time.

For instance,

array(
  [0] => array([0]=>'blue',[1]=>'red'),
  [1] => array([0]=>'sunny',[1]=>'cloudy'),
  [2] => array([0]=>'sweet',[1]=>'acid');

What should I do to get:

array(
  [0] => array([0]=>'blue',[1]=>'sunny',[2]=>'sweet'),
  [1] => array([0]=>'blue',[1]=>'sunny',[2]=>'acid'),
  [2] => array([0]=>'blue',[1]=>'cloudy',[2]=>'sweet'),
  [3] => array([0]=>'blue',[1]=>'cloudy',[2]=>'acid'),
  [4] => array([0]=>'red',[1]=>'sunny',[2]=>'sweet'),
  [5] => array([0]=>'red',[1]=>'sunny',[2]=>'acid'),
  [6] => array([0]=>'red',[1]=>'cloudy',[2]=>'sweet'),
  [7] => array([0]=>'red',[1]=>'cloudy',[2]=>'acid'));

I tried doing this with nested loops, but my logic is not too strong.

Very much appreciated if someone can shed some light

+5
source share
5 answers

(Note: a small modification is required for use in PHP <5.3)

Do this ( example in the online interpreter):

$f = function () { return func_get_args(); };
$res = array_outer($f,
    array("blue", "red"),
    array("sunny", "cloudy"),
    array("sweet", "acid"));

array_outer, Mathematica Outer, :

/**
 * A generalization of the outer product, forming all the possible
 * combinations of the elements of any number of arrays and feeding
 * them to $f.
 * The keys are disregarded
 **/
function array_outer($f, array $array1) {
    $res = array();
    $arrays = func_get_args();
    array_shift($arrays);
    foreach ($arrays as $a) {
        if (empty($a))
            return $res;
    }

    $num_arrays = count($arrays);
    $pos = array_fill(0, $num_arrays, 0);
    while (true) {
        $cur = array();
        for ($i = 0; $i < $num_arrays; $i++) {
            $cur[] = $arrays[$i][$pos[$i]];
        }
        $res[] = call_user_func_array($f, $cur);
        for ($i = $num_arrays-1; $i >= 0; $i--) {
            if ($pos[$i] < count($arrays[$i]) - 1) {
                $pos[$i]++;
                break;
            } else {
                if ($i == 0)
                    break 2;
                $pos[$i] = 0;
            }
        }
    }
    return $res;
}
+8

:

$arr =  array(
            0 => array(0 =>'blue', 1 =>'red'),
            1 => array(0 =>'sunny', 1 =>'cloudy'),
            2 => array(0 =>'sweet', 1 =>'acid')
        );

$combinations = array();
getArrayCombinations($arr, $combinations);
echo '<pre>';print_r($combinations);

/**
 * Creates an array with all possible combinations
 * @param array main_array - Array to find all the possible combinations of
 * @param array combinations - Array to store the resulting array in
 * @param array batch
 * @param int index
 */
function getArrayCombinations($main_array, &$combinations, $batch=array(), $index=0)
{
    if ($index >= count($main_array))
        array_push($combinations, $batch);
    else
        foreach ($main_array[$index] as $element)
        {
            $temp_array = $batch; array_push($temp_array, $element);
            getArrayCombinations($main_array, $combinations, $temp_array, $index+1);
        }
}
+4

, , - :

000
001
010
011
100
101
110
111

, , . , 1:

array(
  [0] => array([0]=>'blue',[1]=>'red'),
  [1] => array([0]=>'sunny'),
  [2] => array([0]=>'sweet',[1]=>'acid');

... , 1:

000
001
100
101

. ? . , reset 0 . , . , reset 0, , . , , .

PHP:

class Sequence implements Iterator {

    private $input;

    private $hasNext;
    private $positions;

    public function __construct(array $input) {
        $this->input = $input;
    }

    public function rewind() {
        $this->hasNext = true;
        $this->positions = array();
        for ($i = 0; $i < count($this->input); $i++) {
            $this->positions[$i] = 0;
        }
    }

    public function valid() {
        return $this->hasNext;
    }

    public function current() {
        $current = array();
        for ($i = 0; $i < count($this->positions); $i++) {
            $current[] = $this->input[$i][$this->positions[$i]];
        }
        return $current;
    }

    public function key() {}

    public function next() {
        for ($i = count($this->positions) - 1; $i >= 0; $i--) {
            if ($this->positions[$i] < count($this->input[$i]) - 1) {
                $this->positions[$i]++;
                break;
            } else {
                $this->positions[$i] = 0;
                $this->hasNext = $i !== 0;
            }
        }
    }

}

next() - . reset() 0 current() .

( "" , ):

$input = array(
    array('blue', 'red'),
    array('sunny'),
    array('sweet', 'acid')
);

$lst = new Sequence($input);
foreach ($lst as $elt) {
    print(implode(', ', $elt) . "\n");
}

:

blue, sunny, sweet
blue, sunny, acid
red, sunny, sweet
red, sunny, acid
+2

:

$arr = array(
    array('a', 'b', 'c'),
    array('x', 'y', 'z'),
    array('1', '2')
);

$result = array();
foreach ($arr as $a) {
    if (empty($result)) {
        $result = $a;
        continue;
    }

    $res = array();
    foreach ($result as $r) {
        foreach ($a as $v) {
            $res[] = array_merge((array)$r, (array)$v);
        }
    }

    $result = $res;
}

var_dump($result);
+2

latenight pseudocode:

result = []
counter = 0
for i in length(array[0]):
  for j in length(array[1]):
    for k in length(array[2]):      
      result[counter] = aray(0: array[0][i], 1: array[1][j], 2: array[2][k])
      counter+=1

,

0

All Articles