Сортировать массив по ключам на основе другого массива? - PullRequest
126 голосов
/ 08 декабря 2008

Возможно ли в PHP сделать что-то подобное? Как бы вы пошли о написании функции? Вот пример. Порядок - самая важная вещь.

$customer['address'] = '123 fake st';
$customer['name'] = 'Tim';
$customer['dob'] = '12/08/1986';
$customer['dontSortMe'] = 'this value doesnt need to be sorted';

И я бы хотел сделать что-то вроде

$properOrderedArray = sortArrayByArray($customer, array('name', 'dob', 'address'));

Потому что в конце я использую foreach (), а они не в правильном порядке (потому что я добавляю значения в строку, которая должна быть в правильном порядке, и я не знаю заранее все ключи / значения массива).

Я просмотрел функции внутреннего массива PHP, но кажется, что вы можете сортировать только по алфавиту или по цифрам.

Ответы [ 15 ]

0 голосов
/ 29 декабря 2016
  • сортировка по запросу
  • сохранить для int-ключей (из-за array_replace)
  • не возвращать ключи не существуют в inputArray
  • (необязательно) фильтр ключей не существует в данном списке ключей

Код:

 /**
 * sort keys like in key list
 * filter: remove keys are not listed in keyList
 * ['c'=>'red', 'd'=>'2016-12-29'] = sortAndFilterKeys(['d'=>'2016-12-29', 'c'=>'red', 'a'=>3 ]], ['c', 'd', 'z']){
 *
 * @param array $inputArray
 * @param string[]|int[] $keyList
 * @param bool $removeUnknownKeys
 * @return array
 */
static public function sortAndFilterKeys($inputArray, $keyList, $removeUnknownKeys=true){
    $keysAsKeys = array_flip($keyList);
    $result = array_replace($keysAsKeys, $inputArray); // result = sorted keys + values from input + 
    $result = array_intersect_key($result, $inputArray); // remove keys are not existing in inputArray 
    if( $removeUnknownKeys ){
        $result = array_intersect_key($result, $keysAsKeys); // remove keys are not existing in keyList 
    }
    return $result;
}
0 голосов
/ 29 октября 2015

Немного поздно, но я не смог найти способ, которым я это реализовал, эта версия требует закрытия, php> = 5.3, но может быть изменена не так:

$customer['address'] = '123 fake st';
$customer['name'] = 'Tim';
$customer['dob'] = '12/08/1986';
$customer['dontSortMe'] = 'this value doesnt need to be sorted';

$order = array('name', 'dob', 'address');

$keys= array_flip($order);
uksort($customer, function($a, $b)use($keys){
    return $keys[$a] - $keys[$b];
});
print_r($customer);

Конечно, 'dontSortMe' нужно отсортировать, и он может появиться первым в примере

0 голосов
/ 25 октября 2014

PHP имеет функции, которые помогут вам в этом:

$arrayToBeSorted = array('west', 'east', 'south', 'north');
$order = array('north', 'south', 'east', 'west');

// sort array
usort($arrayToBeSorted, function($a, $b) use ($order){
    // sort using the numeric index of the second array
    $valA = array_search($a, $order);
    $valB = array_search($b, $order);

    // move items that don't match to end
    if ($valA === false)
        return -1;
    if ($valB === false)
        return 0;

    if ($valA > $valB)
        return 1;
    if ($valA < $valB)
        return -1;
    return 0;
});

Usort делает всю работу за вас, а array_search предоставляет ключи. array_search () возвращает false, когда не может найти совпадение, поэтому элементы, которых нет в массиве sort, естественным образом перемещаются в конец массива.

Примечание: uasort () упорядочит массив, не затрагивая отношения ключ => значение.

0 голосов
/ 25 февраля 2013

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

Array[0] ...
['dob'] = '12/08/1986';
['some_key'] = 'some value';

Array[1] ...
['dob'] = '12/08/1986';

Array[2] ...
['dob'] = '12/08/1986';
['some_key'] = 'some other value';

и поддерживал «главный ключ» примерно так:

$master_key = array( 'dob' => ' ' ,  'some_key' => ' ' );

array_merge выполнил бы слияние в итерации Array [1] на основе $ master_key и произвело бы ['some_key'] = '', пустое значение для этой итерации. Следовательно, array_intersect_key использовался для изменения $ master_key в каждой итерации следующим образом:

foreach ($customer as $customer) {
  $modified_key = array_intersect_key($master_key, $unordered_array);
  $properOrderedArray = array_merge($modified_key, $customer);
}
0 голосов
/ 18 сентября 2012

Первое предложение

function sortArrayByArray($array,$orderArray) {
    $ordered = array();
    foreach($orderArray as $key) {
        if(array_key_exists($key,$array)) {
            $ordered[$key] = $array[$key];
            unset($array[$key]);
        }
    }
    return $ordered + $array;
}

Второе предложение

$properOrderedArray = array_merge(array_flip(array('name', 'dob', 'address')), $customer);

Я хотел бы отметить, что оба эти предложения великолепны. Однако это яблоки и апельсины. Различия? Один не ассоциативный, а другой дружественный. Если вы используете 2 полностью ассоциативных массива, тогда массив merge / flip фактически объединит и перезапишет другой ассоциативный массив. В моем случае это не тот результат, который я искал. Я использовал файл settings.ini, чтобы создать свой массив порядка сортировки. Массив данных, который я сортировал, не должен был перезаписываться моим коллегой по сортировке. Таким образом, слияние массива уничтожит мой массив данных. Оба являются отличными методами, оба должны быть заархивированы в любом наборе инструментов для разработчиков. Исходя из ваших потребностей, вы можете обнаружить, что вам действительно нужны обе концепции в ваших архивах.

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