CRM_Utils_Array - Add helper to rotate an array (from rows to columns)
authorTim Otten <totten@civicrm.org>
Wed, 23 Jun 2021 02:53:07 +0000 (19:53 -0700)
committerTim Otten <totten@civicrm.org>
Tue, 6 Jul 2021 22:49:55 +0000 (15:49 -0700)
CRM/Utils/Array.php
tests/phpunit/CRM/Utils/ArrayTest.php

index 06aa5a8faf634d85fc23cb7cd5431a0c0e3a038a..7e5dd448ab20f0f67f2251e52201c23ce960ce33 100644 (file)
@@ -983,6 +983,34 @@ class CRM_Utils_Array {
     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.
    *
index 7403576c5fb6aab2a96ecfba5be490f597b8526b..5b2318ee76b9416e9f982bc5ad1379ba899b5747 100644 (file)
@@ -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[] = [