src/Debug/MethodTable.php
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;
    }
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;
    }
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