Skip to content
Snippets Groups Projects
Commit 17deafad authored by totten's avatar totten
Browse files

CRM_Utils_Array::product() - Helper to generate Cartesian products

parent 144fb5a0
No related branches found
No related tags found
No related merge requests found
......@@ -635,5 +635,48 @@ class CRM_Utils_Array {
}
return $default;
}
/**
* Generate the Cartesian product of zero or more vectors
*
* @param array $dimensions list of dimensions to multiply; each key is a dimension name; each value is a vector
* @param array $template a base set of values included in every output
* @return array each item is a distinct combination of values from $dimensions
*
* For example, the product of
* {
* fg => {red, blue},
* bg => {white, black}
* }
* would be
* {
* {fg => red, bg => white},
* {fg => red, bg => black},
* {fg => blue, bg => white},
* {fg => blue, bg => black}
* }
*/
static function product($dimensions, $template = array()) {
if (empty($dimensions)) {
return array($template);
}
foreach ($dimensions as $key => $value) {
$firstKey = $key;
$firstValues = $value;
break;
}
unset($dimensions[$key]);
$results = array();
foreach ($firstValues as $firstValue) {
foreach (self::product($dimensions, $template) as $result) {
$result[$firstKey] = $firstValue;
$results[] = $result;
}
}
return $results;
}
}
......@@ -33,7 +33,7 @@ class CRM_Utils_ArrayTest extends CiviUnitTestCase {
$inputs[] = array(
'lang' => 'en',
'msgid' => 'greeting',
'familiar' => false,
'familiar' => FALSE,
'value' => 'Hello'
);
$inputs[] = array(
......@@ -54,7 +54,7 @@ class CRM_Utils_ArrayTest extends CiviUnitTestCase {
$inputs[] = array(
'lang' => 'en',
'msgid' => 'greeting',
'familiar' => true,
'familiar' => TRUE,
'value' => 'Hey'
);
......@@ -82,4 +82,41 @@ class CRM_Utils_ArrayTest extends CiviUnitTestCase {
$this->assertEquals($expected, CRM_Utils_Array::collect('catWord', $arr));
}
function testProduct0() {
$actual = CRM_Utils_Array::product(
array(),
array('base data' => 1)
);
$this->assertEquals(array(
array('base data' => 1),
), $actual);
}
function testProduct1() {
$actual = CRM_Utils_Array::product(
array('dim1' => array('a', 'b')),
array('base data' => 1)
);
$this->assertEquals(array(
array('base data' => 1, 'dim1' => 'a'),
array('base data' => 1, 'dim1' => 'b'),
), $actual);
}
function testProduct3() {
$actual = CRM_Utils_Array::product(
array('dim1' => array('a', 'b'), 'dim2' => array('alpha', 'beta'), 'dim3' => array('one', 'two')),
array('base data' => 1)
);
$this->assertEquals(array(
array('base data' => 1, 'dim1' => 'a', 'dim2' => 'alpha', 'dim3' => 'one'),
array('base data' => 1, 'dim1' => 'a', 'dim2' => 'alpha', 'dim3' => 'two'),
array('base data' => 1, 'dim1' => 'a', 'dim2' => 'beta', 'dim3' => 'one'),
array('base data' => 1, 'dim1' => 'a', 'dim2' => 'beta', 'dim3' => 'two'),
array('base data' => 1, 'dim1' => 'b', 'dim2' => 'alpha', 'dim3' => 'one'),
array('base data' => 1, 'dim1' => 'b', 'dim2' => 'alpha', 'dim3' => 'two'),
array('base data' => 1, 'dim1' => 'b', 'dim2' => 'beta', 'dim3' => 'one'),
array('base data' => 1, 'dim1' => 'b', 'dim2' => 'beta', 'dim3' => 'two'),
), $actual);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment