Php array нестандартная сортировка
Подскажите, пожалуйста, как решить такую задачку:
Есть некий ассоциативный массив вида:
[key_1] => Array
(
[0] => 0
)
[key_2] => Array
(
[0] => 1
)
[key_3] => Array
(
[0] => 1
)
[key_4] => Array
(
[0] => 1
)
[key_5] => Array
(
[0] => 0
)
[key_6] => Array
(
[0] => 0
)
[key_7] => Array
(
[0] => 1
)
Мне надо отсортировать этот массив по значению внутри каждого массива в такой вид, при этом сохранив ключи:
[key_1] => Array
(
[0] => 0
)
[key_2] => Array
(
[0] => 1
)
[key_5] => Array
(
[0] => 0
)
[key_3] => Array
(
[0] => 1
)
[key_6] => Array
(
[0] => 0
)
[key_4] => Array
(
[0] => 1
)
То есть получился массив, где значение ключей чередуются: 0|1|0|1|0|1... Всю голову сломал не пойму как это сделать.
Ответы (2 шт):
Если последовательность ключей не имеет значения, то самый простой вариант "в лоб", сделать так:
Вначале применить сортировку в принципе, по значениям, чтобы был массив вида
[0,0,0,0,1,1,1,1]
. Здесь упрощённая схема, без упоминания ключей, чтобы было понятно.Тут можно применить функцию uasort
Пробежаться циклом по этому массиву и собирать в новый массив по очереди вытаскавая по два значения: один с начала и один с конца, затем один второй элемент с начала и один второй элемент с конца, и т.д..... Можно двигаться попарно так: один элемент с начала и первый элемент от середины, второй элемент с начала и второй элемент с середины, и т.д.
Для цикла может понадобиться:
- Пробегание от начала до середины массива (т.е. до
$i < count($arr) / 2
... В случае если число элементов нечётное то необходимо среднее число округлить в большую сторону и иметь проверку впоследствии на этот нюанс) - array_slice для срезания элемента из отсортированного массива
- Умение формировать динамически ключ массива, например
$key1 = 'key_' . ($i + 1);
- current для того, чтобы извлечь значение массива без ключа
- Пробегание от начала до середины массива (т.е. до
Шаг №2 можно делать по-всякому и можно найти проще варианты. Но суть остаётся - вначале отсортировать, потом распихать.
Можно сделать изначально простой ассоциативный массив в виде key => value
, для упрощения всех манипуляций (также подойдут для этих целей и Map)
Сначала собираем массив ключей, а затем пробегаем по нему двумя указателями:
$a = [
'key_1' => ['0' => 0],
'key_2' => ['0' => 1],
'key_3' => ['0' => 1],
'key_4' => ['0' => 1],
'key_5' => ['0' => 0],
'key_6' => ['0' => 0],
'key_7' => ['0' => 1],
];
$keys = array_keys($a);
$b = [];
$i = $j = $v = 0;
$count = count($a);
while ($i < $count && $j < $count && $z++ < 100) {
while ($i < $count && $a[$keys[$i]][0] != $v /* 0 */) {
$i++;
}
if ($i < $count) {
$b[$keys[$i]] = $a[$keys[$i]];
$i++;
$v = 1 - $v;
}
while ($j < $count && $a[$keys[$j]][0] != $v /* 1 */) {
$j++;
}
if ($j < $count) {
$b[$keys[$j]] = $a[$keys[$j]];
$j++;
$v = 1 - $v;
}
}
var_export($b);
Если же в массиве преобладание какого-то значения, а отбрасывать лишние значения нельзя, то не используем переменную $v, а сравниваем непосредственно с 0 и 1.
$z - техническая переменная от случайного зацикливания.