Skip to content

Instantly share code, notes, and snippets.

@xphere
Created December 4, 2013 10:54
Show Gist options
  • Select an option

  • Save xphere/7785740 to your computer and use it in GitHub Desktop.

Select an option

Save xphere/7785740 to your computer and use it in GitHub Desktop.
Iterates over all combinations of the values on an input array
<?php
class CombinatorialIterator implements \Iterator
{
protected $valid;
protected $iteration;
protected $data;
public function __construct(array $data = array())
{
$this->data = $data;
}
public function current()
{
$result = array();
foreach ($this->data as $name => $value) {
$result[$name] = is_array($value) ? current($value) : $value;
}
return $result;
}
public function next()
{
$this->valid = false;
foreach ($this->data as $name => $value) {
if (is_array($value)) {
next($this->data[$name]);
if (key($this->data[$name]) !== null) {
$this->valid = true;
break;
}
reset($this->data[$name]);
}
}
++$this->iteration;
}
public function key()
{
return $this->iteration;
}
public function valid()
{
return $this->valid;
}
public function rewind()
{
$this->valid = !empty($this->data);
$this->iteration = 0;
foreach ($this->data as $name => $value) {
if (is_array($value)) {
reset($this->data[$name]);
}
}
}
}
<?php
class CombinatorialIteratorTest extends \PHPUnit_Framework_TestCase
{
public function testEmptyConstruction()
{
$iterator = new CombinatorialIterator();
$this->assertNotNull($iterator);
}
/**
* @dataProvider providerValidInput
*/
public function testValidInput($input, $expected)
{
$this->assertEquals($expected, iterator_to_array(new CombinatorialIterator($input)));
}
public function providerValidInput()
{
return array(
'default' => array(
array(),
array(),
),
'single scalar' => array(
array('scalar' => 'value'),
array(
array('scalar' => 'value'),
),
),
'multiple scalar' => array(
array('scalar1' => 'value1', 'scalar2' => 'value2'),
array(
array('scalar1' => 'value1', 'scalar2' => 'value2'),
),
),
'single array' => array(
array('option' => array('first', 'second')),
array(
array('option' => 'first'),
array('option' => 'second'),
),
),
'multiple array' => array(
array(
'name' => array('Bob', 'John'),
'surname' => array('Spongebob', 'Snow'),
),
array(
array('name' => 'Bob', 'surname' => 'Spongebob', ),
array('name' => 'John', 'surname' => 'Spongebob', ),
array('name' => 'Bob', 'surname' => 'Snow', ),
array('name' => 'John', 'surname' => 'Snow', ),
),
),
'mixed' => array(
array(array('A', 'B'), 'C', array('D', 'E', 'F'), 'G'),
array(
array('A', 'C', 'D', 'G'),
array('B', 'C', 'D', 'G'),
array('A', 'C', 'E', 'G'),
array('B', 'C', 'E', 'G'),
array('A', 'C', 'F', 'G'),
array('B', 'C', 'F', 'G'),
),
),
);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment