Сортировка массивов объектов по предопределенной карте значений

У меня есть следующие массивы:

$inputArray = Array(
[0] => stdClass Object (
[id] => 8
)

[1] => stdClass Object (
[id] => 7
)

[2] => stdClass Object (
[id] => 5
)
)

$sortingArray = [5,8,1]

Я ищу эффективный способ сортировки входного массива по идентификатору «карта значений». Ожидаемый результат должен быть переупорядочен в $ inputArray, чтобы третий элемент был первым, первый элемент — вторым и т. Д.

Спасибо!

1

Решение

Я использовал несколько вещей здесь, главное, что я использую сортировочный массив в качестве цели для 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() так что я могу установить нулевое значение, которое позволяет фильтру работать.

1

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

Ты можешь использовать 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
)

)
2

Прежде всего, если ваш входной массив является результирующим набором запроса MySQL, вы должны сортировать данные с помощью предложения ORDER BY. FIELD() это отличный инструмент для работы, с небольшой странностью, что вам нужно изменить логику сортировки и написать DESC после функции.

Ресурс: https://www.electrictoolbox.com/mysql-order-specific-field-values/ (прокрутите вниз, чтобы «получил»)

Демонстрация SQL Fiddle: http://sqlfiddle.com/#!9/6b996f/1


Кроме того, я предложу две усовершенствованные версии решений Найджела и Эдди, использующие некоторые преимущества php7 +. Какой из них вы выберете для реализации, будет связан с:

  1. Хотите ли вы разрешить элементы с дубликатом id значения, чтобы «пережить» процесс
  2. Какой из них работает более эффективно для вашего фактический данные проекта (размер вашего входного массива и ваш массив пользовательских заказов)
  3. Персональные предпочтения (оба фрагмента могут быть разумно написаны в 3-5 строк, поэтому краткость не является критерием)

Решение № 1: usort () а также нулевой оператор объединения

PHP Demo

$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, но я решил добавить данные выбросов в массив поиска.

* Я использовал круглые скобки в своей пользовательской функции не только для улучшения читабельности, но и для гарантии того, что оценка выполняется должным образом — на самом деле я не удосужился проверить, является ли оценка такой же без группировки в скобках.

Решение № 2: array_replace () перевернутый & отфильтрованный массив сортировки с массивом с ключами

(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 значения во входном массиве.

0
По вопросам рекламы [email protected]