PHP Сортировка массива по алфавиту, за исключением ОДНОГО значения сверху, для выпадающего меню
Я пытаюсь взломать раскрывающееся меню, извлекающее информацию из множества стран, чтобы вверху отображалось "Соединенные Штаты" (id 1), а все остальные страны сортировались в алфавитном порядке. Как мне отсортировать все, кроме США, чтобы остаться на вершине, используя функцию usort для массива? Любые альтернативные предложения также приветствуются. Вот код:
while (list($key, $value) = each($countries->countries)) {
$countries_array[] = array('id' => $key, 'text' => $value['countryname']);
}
function text_cmp($a, $b) {
return strcmp($a["text"], $b["text"]);
}
usort($countries_array, 'text_cmp');
5 ответов
Вообще говоря, вы можете повторно ввести свой массив, затем отсортировать по ключам, затем объединить массив с измененным ключом с массивом с одинокой строкой US, а затем повторно проиндексировать массив. Однако я не рекомендую его, потому что количество итераций, необходимых в процессе, непривлекательно велико. Другими словами, временная сложность неоптимальна.
$keyed = array_column($countries, null, 'text');
ksort($keyed);
var_export(array_values(['United States' => $keyed['United States']] + $keyed));
Вы также можете позвонитьarray_search()
сarray_column()
изолируя значения, но в любом случае потребуется отсортировать столбец по алфавиту. Итак, опять же, я бы исключил это из соображений эффективности. Я бы также не рекомендовал какой-либо подход с использованиемin_array()
.
Правда в том, что эту задачу можно выполнить с помощью одногоusort()
вызов.
Код: (Демо)
usort(
$countries,
fn($a, $b) =>
[$a['text'] !== 'United States', $a['text']]
<=>
[$b['text'] !== 'United States', $b['text']]
);
var_export($countries);
Предоставляя$a
данные слева от оператора космического корабля и$b
данные справа, сортировка ASC отключена.
Сортировка по возрастанию логических значений ставитfalse
доtrue
. Чтобы убедиться, что строка US всегда имеет более высокий приоритет, чем любая другая строка, проверьте, является ли значение НЕ .
Первый элемент с каждой стороны оператора космического корабля — это первое правило. Когда обаtext
значения неUnited States
, то применяется стандартная алфавитная сортировка.
Это очень эффективный подход, поскольку нет повторных вызовов функций.
Наконец, поскольку вы создаете новую, определенную структуру массива изcountries
собственность вашего$countries
объект внутри цикла, вы могли бы лучше использовать этот цикл. Может быть, что-то вроде этого:
$result = [];
foreach ($countries->countries as $id => ['countryname' => $text]) {
$row = compact(['id' 'text']);
if ($text === 'United States') {
$result[] = $row;
} else {
$theRest[] = $row;
$texts[] = $text;
}
}
array_multisort($texts, $theRest);
array_push($result, ...$theRest);
var_export($result);
Самый простой способ сделать это - удалить одно значение, отсортировать, а затем снова добавить его:
// your countries array goes here:
$countries = array(2=>"Burma", 4=>"Zimbabwe", 10=>"France", 1=>"United States", 13=>"Russia");
$AmericaFKYeah = array(1=>"United States");
$countries =array_diff($countries, $AmericaFKYeah);
asort($countries);
// using + instead of array_unshift() preserves numerical keys!
$countries= $AmericaFKYeah + $countries;
дает тебе:
array(5) {
[1]=>
string(13) "United States"
[2]=>
string(5) "Burma"
[10]=>
string(6) "France"
[13]=>
string(6) "Russia"
[4]=>
string(8) "Zimbabwe"
}
С индексированным массивом
меры
- Найти ресурс в массиве
- Unset переменная в массиве
- Добавить ресурс в качестве первого элемента в массиве с помощью array_unshift (array_unshift - добавить один или несколько элементов к началу массива - http://php.net/manual/en/function.array-unshift.php)
Код
if (in_array('yourResource', $a_array)){
unset($a_array[array_search('yourResource',$a_array)]);
array_unshift($a_array, 'yourResource');
}
С многомерными массивами
$yourResorceToFind = 'yourResource';
foreach ($a_arrays as $a_sub_array){
if (in_array($yourResorceToFind, $a_sub_array)){
unset($a_arrays[array_search($yourResorceToFind,$a_sub_array)]);
array_unshift($a_arrays, $a_sub_array);
break;
}
}
Попробуй это:
<?php
$array = array('Alpha', 'atomic', 'Beta', 'bank');
$array_lowercase = array_map('strtolower', $array);
array_multisort($array_lowercase, SORT_ASC, SORT_STRING, $array);
print_r($array);
?>
выход:
Array
([0] => Alpha [1] => atomic [2] => bank [3] => Beta)
или же:
$arr1 = array(
array('id'=>1,'name'=>'aA','cat'=>'cc'),
array('id'=>2,'name'=>'aa','cat'=>'dd'),
array('id'=>3,'name'=>'bb','cat'=>'cc'),
array('id'=>4,'name'=>'bb','cat'=>'dd')
);
$arr2 = array_msort($arr1, array('name'=>SORT_DESC, 'cat'=>SORT_ASC));
Я обнаружил, что эта тема пытается сделать то же самое уродливым способом, но поскольку моя техника кажется более простой, я делюсь ею, если кому-то нужно.
Самый простой способ сделать это - повозиться с результатом обратного вызова usort. Вам просто нужно сначала передать желаемое значение в обратном вызове следующим образом:
$countries = [
['id' => 2, 'text' => 'Burma'],
['id' => 4, 'text' => 'Zimbabwe'],
['id' => 10, 'text' => 'France'],
['id' => 1, 'text' => 'United States'],
['id' => 13, 'text' => 'Russia'],
];
$myFirstItem = "United States";
usort($countries, function($a, $b) use ($myFirstItem) {
return $myFirstItem == $a['text'] ? -1 : ($myFirstItem == $b['text'] ? 1 : strcmp($a['text'], $b['text']));
});
Это некрасиво, но выполняет свою работу без необходимости играть с другими массивами, и все, как и ожидалось, выполняется в обратном вызове.