У меня есть следующие массивы:
$inputArray = Array(
[0] => stdClass Object (
[id] => 8
)
[1] => stdClass Object (
[id] => 7
)
[2] => stdClass Object (
[id] => 5
)
)
$sortingArray = [5,8,1]
Я ищу эффективный способ сортировки входного массива по идентификатору «карта значений». Ожидаемый результат должен быть переупорядочен в $ inputArray, чтобы третий элемент был первым, первый элемент — вторым и т. Д.
Спасибо!
Я использовал несколько вещей здесь, главное, что я использую сортировочный массив в качестве цели для array_replace()
и я использую array_column()
индексировать объекты (для работы с объектами необходим PHP 7.0+) …
$input = array_column($inputArray, null, "id");
$sort = array_fill_keys($sortingArray, null);
$output = array_filter(array_replace($sort, $input));
array_filter()
удалит все элементы, которые находятся не во входном массиве, а в массиве сортировки. array_fill_keys()
используется вместо array_flip()
так что я могу установить нулевое значение, которое позволяет фильтру работать.
Ты можешь использовать array_flip
сделать временный массив. Это перевернет массив означает, что значения будут ключом.
использование usort
отсортировать массив.
$tempArr = array_flip( $sortingArray );
usort($inputArray, function($a, $b) use ( $tempArr ) {
$tempA = isset( $tempArr[ $a->id ] ) ? $tempArr[ $a->id ] : 999999; //If id does not exist on $sortingArray. Use 999999 as an index
$tempB = isset( $tempArr[ $b->id ] ) ? $tempArr[ $b->id ] : 999999;
return $tempA - $tempB;
});
echo "<pre>";
print_r( $inputArray );
echo "</pre>";
Это приведет к:
Array
(
[0] => stdClass Object
(
[id] => 5
)
[1] => stdClass Object
(
[id] => 8
)
[2] => stdClass Object
(
[id] => 7
)
)
Прежде всего, если ваш входной массив является результирующим набором запроса MySQL, вы должны сортировать данные с помощью предложения ORDER BY. FIELD()
это отличный инструмент для работы, с небольшой странностью, что вам нужно изменить логику сортировки и написать DESC
после функции.
Ресурс: https://www.electrictoolbox.com/mysql-order-specific-field-values/ (прокрутите вниз, чтобы «получил»)
Демонстрация SQL Fiddle: http://sqlfiddle.com/#!9/6b996f/1
Кроме того, я предложу две усовершенствованные версии решений Найджела и Эдди, использующие некоторые преимущества php7 +. Какой из них вы выберете для реализации, будет связан с:
id
значения, чтобы «пережить» процесс$array = [
(object)['id' => 8],
(object)['id' => 7],
(object)['id' => 5]
];
$order = [5, 8, 1]; // custom sort order
$order = array_flip($order); // restructure for easy lookup with isset()
$order[''] = max(array_column($array, 'id')) + 1; // append value higher than max for outlying ids
usort($array, function($a, $b) use ($order) {
return ($order[$a->id] ?? $order['']) <=> ($order[$b->id] ?? $order['']);
});
var_export($array);
* обратите внимание, что я мог бы пройти $outlier
в область пользовательских функций в качестве второго use
аргумент и заменил все $order['']
переменные с $outlier
, но я решил добавить данные выбросов в массив поиска.
* Я использовал круглые скобки в своей пользовательской функции не только для улучшения читабельности, но и для гарантии того, что оценка выполняется должным образом — на самом деле я не удосужился проверить, является ли оценка такой же без группировки в скобках.
(PHP Demo)
$array = [
(object)['id' => 8],
(object)['id' => 7],
(object)['id' => 5]
];
$order = [5, 8, 1];
$order = array_flip($order); // flip for future key comparisons
$keyed = array_column($array, null, 'id'); // declare id values as new keys
$filtered_order = array_intersect_key($order, $keyed); // remove unwanted order keys
$replaced = array_replace($filtered_order, $keyed); // apply objects to output array
var_export(array_values($replaced)); // re-index the output (if desired)
* обратите внимание, что это не приведет к созданию массива null
значения, и он не будет удалять значения, которые являются «фальсией».
* Я снова скажу, что использование array_column()
повредит данные, если есть дубликаты id
значения во входном массиве.