Как отсортировать массив по значениям подмассива с неизвестным индексом - PullRequest
0 голосов
/ 11 марта 2019

У меня есть этот массив PHP:

<?php 

$cities = [
    'amsterdam' => $amsterdam,
    'prague'    => $prague,
    'lisboa'    => $lisboa
];

$amsterdam = [
    65 => [
        'table'     => Object
        'something' => false,
        'data'      => [
            'foo'    => 'boo',
            'price'   => 100
        ]
    ],
    173 => [
        'table'     => Object
        'something' => false,
        'data'      => [
            'foo'    => 'hoo',
            'price'   => 2500
        ]
    ],
    ...
];

$prague    = [
    132 => [
        'table'     => Object
        'something' => false,
        'data'      => [
            'foo'    => 'boo',
            'price'   => 2100
        ]
    ],
    956 => [
        'table'     => Object
        'something' => false,
        'data'      => [
            'foo'    => 'hoo',
            'price'   => 2500
        ]
    ],
    ...
];

$lisboa    = [
    175 => [
        'table'     => Object
        'something' => false,
        'data'      => [
            'foo'    => 'boo',
            'price'   => 6500
        ]
    ],
    64 => [
        'table'     => Object
        'something' => false,
        'data'      => [
            'foo'    => 'hoo',
            'price'   => 20
        ]
    ],
    ...
];

?>

и мне нужно отсортировать его по значению подмассива ['data'] ['price'], чтобы результат выглядел следующим образом:

<?php
    $cheapest_cities [
        'lisboa'    => $lisboa,    // because 64->data->price is 20
        'amsterdam' => $amsterdam, // beacuse 65->data->price is 100
        'prague'    => $prague     // bacause 132->data->price is 2100
    ];
?>

Я пробовал несколько комбинаций usort, но проблема в том, что я никогда не знаю, каким будет индекс подмассива (65, 173, 132, 956, 175, 64) в моем примере.

У вас есть идеи, как это отсортировать?

Данные поступают из базы данных:

<?php

        $amsterdam  = $this->getTable()->where(['package_id' => [1,2,3]])->order('package_id')->fetchPairs('id');
        $lisboa     = $this->getTable()->where(['package_id' => [4,5]])->order('package_id')->fetchPairs('id');
        $prague     = $this->getTable()->where(['package_id' => [6]])->order('package_id')->fetchPairs('id');

        return [
            'amsterdam'     => $amsterdam,
            'lisboa'        => $lisboa,
            'prague'        => $prague,
        ];

?>

Спасибо

Ответы [ 2 ]

1 голос
/ 11 марта 2019

Я бы начал с создания нового массива, который имеет наименьшую цену каждого города в качестве значения

. Для этого я использую функцию array_map, которая уменьшает элементы $ доцена с array_reduce

$map_prices = function($n) { 
    $reduce_smallest_price = function($carry, $item) {
        return $item['data']['price'] < $carry 
                                      ? $item['data']['price'] 
                                      : $carry; 
    };
    return array_reduce($n, $reduce_smallest_price, INF); 

};

$cities_price = array_map($map_prices, $cities);

asort($cities_price);

Я использую этот массив цен для сортировки исходного массива с uksort

uksort($cities, function($a, $b) { 
    global $cities_price; 
    return strnatcmp($cities_price[$a], $cities_price[$b]);

});

Здесьживой пример на 3v4l: https://3v4l.org/8B9VN

0 голосов
/ 11 марта 2019

Не используйте usort, так как это удалит ваши ключи. Используйте uasort.

Просто быстрая идея: Внутри функции обратного вызова uasort вы можете искать минимум вашего элемента, например, через array_reduce.

array_reduce($city, function($carry, $item) {
    return $carry === 0 ? $item['data']['price'] : min($carry, $item['data']['price']);
}, 0);

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

Полный пример :

function getMinimumPrice($cityArray) {
    return array_reduce($cityArray, function($carry, $item) {
        return $carry === 0 ? $item['data']['price'] : min($carry, $item['data']['price']);
    }, 0);
}

uasort($cities, function($city1, $city2) {
    $priceCity1 = getMinimumPrice($city1);
    $priceCity2 = getMinimumPrice($city2);

    return $priceCity1 <=> $priceCity2;
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...