Сортировка массивов объектов по предопределенной карте значений - PullRequest
0 голосов
/ 09 октября 2018

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

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

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

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

$sortingArray = [5,8,1]

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

спасибо!

Ответы [ 3 ]

0 голосов
/ 09 октября 2018

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

0 голосов
/ 11 октября 2018

Прежде всего, если ваш входной массив является результирующим набором запроса 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 голосов
/ 09 октября 2018

Вы можете использовать array_flip для создания временного массива.Это перевернет массив означает, что значения будут ключом.

Используйте usort для сортировки массива.

<code>$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 "
";

Это приведет к:

Array
(
    [0] => stdClass Object
        (
            [id] => 5
        )

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

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

)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...