массивы — более эффективный метод сортировки буквенно-цифровых ключей

ПРИМЕЧАНИЕ. Я отредактировал пример и заменил все значения на 1. Значения не имеют значения, только ключи. Предыдущие значения, которые я написал, привели к недоразумению. Сожалею.

ПРИМЕЧАНИЕ: блоки a / b всегда непрерывны. Я добавляю это, потому что это не было ясно. Если есть 3a / 3b и 5a / 5b, всегда будет 4a / 4b, а не только 4.

У меня есть массивы, которые содержат пронумерованные ключи с ведущими нулями. Иногда эти пронумерованные ключи имеют два варианта, которые я различаю, используя суффиксы a и b. Количество клавиш с вариациями или без них неизвестно, однако не может быть более двух цифр; то есть самая высокая цифровая клавиша ’09’.

Проблема заключается в том, что эти ключи массива должны быть отсортированы численно, но при наличии суффиксов они должны иметь приоритет. Использование ksort () само по себе не позволяет этого достичь.

Например, ksort () дает мне это:

$arr = array(
'01' => 1,
'02' => 1,
'03a' => 1,
'03b' => 1,
'04a' => 1,
'04b' => 1,
'05a' => 1,
'05b' => 1,
'06' => 1,
);

Но мне нужно это:

$arr = array(
'01' => 1,
'02' => 1,
'03a' => 1,
'04a' => 1,
'05a' => 1,
'03b' => 1,
'04b' => 1,
'05b' => 1,
'06' => 1,
);

Я использую какую-то модную гимнастику кодирования, чтобы получить то, что я хочу, но это не красиво. Мне интересно, есть ли лучший, более чистый способ?


Вот что я делаю.

1) Я использую ksort (), который дает мне первый из двух массивов выше. (Тот, который еще не то, что я хочу.)

2) Я создаю два массива. Один для суффиксов ‘a’, другой для суффиксов ‘b’.

$arr_a = array();
$arr_b = array();

foreach ($arr as $k => $v) {
if (substr($k, 2) == 'a') {
$arr_a[$k] = $v;
} else if (substr($k, 2) == 'b') {
$arr_b[$k] = $v;
}
}

3) Я объединяю два массива суффиксов.

$arr_suffixes = array_merge($arr_a, $arr_b);

4) Я разрезаю свой исходный массив так, чтобы получить часть до суффиксов, а часть после суффиксов.

$i = array_search(key($arr_suffixes), array_keys($arr));
$length = count($arr_suffixes);

$arr_before_suffixes = array_slice($arr, 0, $i);
$arr_after_suffixes = array_slice($arr, $i + $length);

5) Используя array_merge, я рекомбинирую нарезанные массивы, чтобы создать нужный мне массив.

$arr = array_merge($arr_before_suffixes, $arr_suffixes);
$arr = array_merge($arr, $arr_after_suffixes);

Наконец, у нас есть правильный $ arr. Разве нет лучшего способа сделать это? Это действительно ужасно.

4

Решение

У вас нет формализованного правила. Я постараюсь угадать.

$arr = array(
'01' => 1,
'02' => 1,
'03a' => 1,
'03b' => 1,
'04a' => 1,
'04b' => 1,
'05a' => 1,
'05b' => 1,
'06' => 1,
);

uksort($arr, function($item1, $item2)
{
$last1 = substr($item1, -1);
$last2 = substr($item2, -1);
// one of the items is a number or last letters matches
if (is_numeric($last1) || is_numeric($last2) || $last1 == $last2)
// simple number comparison
return $item1 - $item2;
else
// natural order comparison
return $last1 > $last2 ? 1 : -1;
});

var_dump($arr);
4

Другие решения

$arr = array(
'01' => 1,
'02' => 2,
'03a' => 3,
'03b' => 6,
'04a' => 4,
'04b' => 7,
'05a' => 5,
'05b' => 8,
'06' => 9,
);

uksort(
$arr,
function($a, $b) {
sscanf($a, '%d%s', $an, $as);
sscanf($b, '%d%s', $bn, $bs);
if ($as === null || $bs === null || $as === $bs) {
return $an - $bn;
}
return strcmp($as, $bs);
}
);
var_dump($arr);
3

natsort () Функция воли поможет вам:

$arr = array(
'01' => 1,
'02' => 1,
'03a' => 1,
'03b' => 1,
'04a' => 1,
'04b' => 1,
'05a' => 1,
'05b' => 1,
'06' => 1,
);
$keys = array_keys($arr);
natsort($keys);
$result = array();
foreach ($keys as $key) {
$result[$key] = $arr[$key];
}
print_r($result); // Your expected result
2
По вопросам рекламы [email protected]