code: public static function colKeys($rows)
      {
          if (!\is_array($rows)) {
              return array();
          }
          if (Abstracter::isAbstraction($rows) && $rows['traverseValues']) {
              $rows = $rows['traverseValues'];
          }
          $lastKeys = array();
          $newKeys = array();
          $curKeys = array();
          foreach ($rows as $row) {
              $curKeys = self::keys($row);
              if (empty($lastKeys)) {
                  $lastKeys = $curKeys;
              } elseif ($curKeys != $lastKeys) {
                  $newKeys = array();
                  $count = \count($curKeys);
                  for ($i = 0; $i < $count; $i++) {
                      $curKey = $curKeys[$i];
                      if ($lastKeys && $curKey === $lastKeys[0]) {
                          \array_push($newKeys, $curKey);
                          \array_shift($lastKeys);
                      } elseif (false !== $position = \array_search($curKey, $lastKeys, true)) {
                          $segment = \array_splice($lastKeys, 0, $position+1);
                          \array_splice($newKeys, \count($newKeys), 0, $segment);
                      } elseif (!\in_array($curKey, $newKeys, true)) {
                          \array_push($newKeys, $curKey);
                      }
                  }
                  // put on remaining from lastKeys
                  \array_splice($newKeys, \count($newKeys), 0, $lastKeys);
                  $lastKeys = \array_unique($newKeys);
              }
          }
          return $lastKeys;
      }
docs: Go through all the "rows" of array to determine what the keys are and their order
  
  @param array $rows array (or traversable abstraction)
  
  @return array