Сортировка с модулем

Я пытаюсь сортировать список в столбцы с помощью uksort.

Массив уже альфа отсортирован, поэтому он похож на array('A','B','C','D','E','F','G','H','I','J','K','L','M')

Который отображается в html, как плавающие элементы:

 ABCD EFGH IJKL M 

Я хочу, чтобы он был переупорядочен, поэтому он выглядит следующим образом:

 AEHK BFIL CGJM D 

Таким образом, отсортированным массивом будет: array('A','E','H','K','B','F','I','L','C','G','J','M','D'

В принципе, то же, что и сортировка списка по алфавиту с модулем, но для php. Я попытался принять решение для javascript и преобразовать его в php, но я не понимаю, что правильно. У кого-нибудь есть идеи, как это сделать в php?

Вот что я пробовал:

 function cmp_nav_by4($a, $b) { if (($a % 5) < ($b % 5)) { return 1; } elseif (($a % 4) > ($b % 4)) { return -1; } else { return $a < $b ? 1 : -1; } } $result = uksort($thearray, "cmp_nav_by4"); 

Настройка следующего:

 $array = range('A', 'M'); $columns = 4; $length = count($array); print_matrix($array, $columns); 

Который выводит каждый член и его ключ по индексу (строка и colum), а также порядок элементов сверху:

 One row - ABCDEFGHIJKLM A[ 0] B[ 1] C[ 2] D[ 3] E[ 4] F[ 5] G[ 6] H[ 7] I[ 8] J[ 9] K[10] L[11] M[12] 

Связанный код javascript можно легко преобразовать в PHP. Однако, если вы внимательно посмотрите на этот вопрос / ответ, станет ясно, что он работает только с полными строками, например, с моей предыдущей попыткой:

 function callback_sort($array, $columns) { $sort = function($columns) { return function($a, $b) use ($columns) { $bycol = ($a % $columns) - ($b % $columns); return $bycol ? : $a - $b; }; }; uksort($array, $sort(4)); return $array; } 

Вывод:

 One row - AEIMBFJCGKDHL A[ 0] E[ 4] I[ 8] M[12] B[ 1] F[ 5] J[ 9] C[ 2] G[ 6] K[10] D[ 3] H[ 7] L[11] 

Так что функция, представленная в другом вопросе, не работает.

Но поскольку массив уже отсортирован, вам не нужно сортировать его снова, а просто изменить порядок или элементы. Но какой порядок? Если матрица не завершена, например, nxn полностью заполняется, для каждого столбца нужно вычислить другой новый индекс. Взятый пример с 13 элементами ( AM ) дает вам следующее распределение строк на столбец:

 column: 1 2 3 4 rows: 4 3 3 3 

Поэтому для каждого столбца значение отличается. Например, в индексе 12, 13-й элемент находится в 4-й строке. По пути, поступающему в эту позицию, он был пропущен 4 раза через колонку 1 и 3 раза в других столбцах 2-4. Поэтому, чтобы получить виртуальный индекс итерированного индекса, вам нужно так суммировать, как часто вы были в каждом столбце, чтобы узнать, сколько чисел в исходном индексе вы продвигали вперед. Если вы перейдете к максимальному количеству членов, вы продолжаете на 0.

Таким образом, это можно было бы итеративно решить, шаг за шагом по каждому индексу распределить вычисление по индексам:

 Index 0: No column: 0 Index 1: 1x in column is which has 4 rows: 4 Index 2: 1x in column 1 (4 rows) and 1x in other columns (3 rows): 4 + 3 

… и так далее. Если виртуальный индекс превышает 12, он начнется с 0, например, для 5-го элемента (индекс 4) виртуальный индекс будет вычислять 13:

 Index 4: 1x 4 rows and 3x 3 rows = 13 (4 + 9) 13 > 12 => 1 (13 - 12) 

Теперь, заполняя новый массив, начиная с виртуального индекса 0 и каждый раз присваивая соответствующее смещение (посмотрите, в каком столбце вы указываете, добавьте количество строк этого столбца, оберните, если необходимо) даст желаемый результат:

 One row - AEHKBFILCGJMD A[ 0] E[ 4] H[ 7] K[10] B[ 1] F[ 5] I[ 8] L[11] C[ 2] G[ 6] J[ 9] M[12] D[ 3] 

Написанный в коде, это простой foreach над исходными индексами. Поддерживая также индекс ключей, это работает с любым массивом, даже с строковыми ключами:

 $floor = floor($length/$columns); $modulo = $length % $columns; $max = $length-1; $virtual = 0; $keys = array_keys($array); $build = array(); foreach($keys as $index => $key) { $vkey = $keys[$virtual]; $build[$vkey] = $array[$vkey]; $virtual += $floor + ($index % $columns < $modulo); ($virtual>$max) && $virtual %= $max; } print_matrix($build, $columns); 

И это все: Демо , Гист .

@hakre имеет правильный ответ кода. Почему:

Основная функция сортировки, Zend_qsort, фактически не изменяет порядок элементов и ключей. Вместо этого он переупорядочивает внутренние ведра, используемые движком zend. Если вы ksort численно проиндексированный массив, то итерации с $q = count($array);for($i=0; $i<$q); $i++) $q = count($array);for($i=0; $i<$q); $i++) он вернет значения точно так же, как и раньше; если вы итерации с for($key in $array) вы получите новый порядок ключей.