From 988664a613ff09e336c391c31e2e1fa555081bbe Mon Sep 17 00:00:00 2001 From: Tim Otten Date: Tue, 22 Jun 2021 19:53:07 -0700 Subject: [PATCH] CRM_Utils_Array - Add helper to rotate an array (from rows to columns) --- CRM/Utils/Array.php | 28 ++++++++++++++++++++++++ tests/phpunit/CRM/Utils/ArrayTest.php | 31 +++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/CRM/Utils/Array.php b/CRM/Utils/Array.php index 06aa5a8faf63..7e5dd448ab20 100644 --- a/CRM/Utils/Array.php +++ b/CRM/Utils/Array.php @@ -983,6 +983,34 @@ public static function filterColumns($matrix, $columns) { return $newRows; } + /** + * Rotate a matrix, converting from row-oriented array to a column-oriented array. + * + * @param iterable $rows + * Ex: [['a'=>10,'b'=>'11'], ['a'=>20,'b'=>21]] + * Formula: [scalar $rowId => [scalar $colId => mixed $value]] + * @param bool $unique + * Only return unique values. + * @return array + * Ex: ['a'=>[10,20], 'b'=>[11,21]] + * Formula: [scalar $colId => [scalar $rowId => mixed $value]] + * Note: In unique mode, the $rowId is not meaningful. + */ + public static function asColumns(iterable $rows, bool $unique = FALSE) { + $columns = []; + foreach ($rows as $rowKey => $row) { + foreach ($row as $columnKey => $value) { + if (FALSE === $unique) { + $columns[$columnKey][$rowKey] = $value; + } + elseif (!in_array($value, $columns[$columnKey] ?? [])) { + $columns[$columnKey][] = $value; + } + } + } + return $columns; + } + /** * Rewrite the keys in an array. * diff --git a/tests/phpunit/CRM/Utils/ArrayTest.php b/tests/phpunit/CRM/Utils/ArrayTest.php index 7403576c5fb6..5b2318ee76b9 100644 --- a/tests/phpunit/CRM/Utils/ArrayTest.php +++ b/tests/phpunit/CRM/Utils/ArrayTest.php @@ -6,6 +6,37 @@ */ class CRM_Utils_ArrayTest extends CiviUnitTestCase { + public function testAsColumns() { + $rowsNum = [ + ['a' => 10, 'b' => 11], + ['a' => 20, 'b' => 21], + ['a' => 20, 'b' => 29], + ]; + + $rowsAssoc = [ + '!' => ['a' => 10, 'b' => 11], + '@' => ['a' => 20, 'b' => 21], + '#' => ['a' => 20, 'b' => 29], + ]; + + $this->assertEquals( + ['a' => [10, 20, 20], 'b' => [11, 21, 29]], + CRM_Utils_Array::asColumns($rowsNum) + ); + $this->assertEquals( + ['a' => [10, 20], 'b' => [11, 21, 29]], + CRM_Utils_Array::asColumns($rowsNum, TRUE) + ); + $this->assertEquals( + ['a' => ['!' => 10, '@' => 20, '#' => 20], 'b' => ['!' => 11, '@' => 21, '#' => 29]], + CRM_Utils_Array::asColumns($rowsAssoc) + ); + $this->assertEquals( + ['a' => [10, 20], 'b' => [11, 21, 29]], + CRM_Utils_Array::asColumns($rowsAssoc, TRUE) + ); + } + public function testIndexArray() { $inputs = []; $inputs[] = [