Сортировка массива по ключам на основе другого массива?
Возможно ли в 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, но, похоже, вы можете сортировать только по алфавиту или по номеру.
Ответы
Ответ 1
Просто используйте array_merge
или array_replace
. array_merge
работает, начиная с массива, который вы ему даете (в правильном порядке) и перезаписывания/добавления ключей с данными из вашего фактического массива:
$customer['address'] = '123 fake st';
$customer['name'] = 'Tim';
$customer['dob'] = '12/08/1986';
$customer['dontSortMe'] = 'this value doesnt need to be sorted';
$properOrderedArray = array_merge(array_flip(array('name', 'dob', 'address')), $customer);
//Or:
$properOrderedArray = array_replace(array_flip(array('name', 'dob', 'address')), $customer);
//$properOrderedArray -> array('name' => 'Tim', 'address' => '123 fake st', 'dob' => '12/08/1986', 'dontSortMe' => 'this value doesnt need to be sorted')
ps - Я отвечаю на этот "устаревший" вопрос, потому что я думаю, что все циклы, представленные в качестве предыдущих ответов, являются излишними.
Ответ 2
Там вы идете:
function sortArrayByArray(array $array, array $orderArray) {
$ordered = array();
foreach ($orderArray as $key) {
if (array_key_exists($key, $array)) {
$ordered[$key] = $array[$key];
unset($array[$key]);
}
}
return $ordered + $array;
}
Ответ 3
Другой способ для PHP >= 5.3.0:
$customer['address'] = '123 fake st';
$customer['name'] = 'Tim';
$customer['dob'] = '12/08/1986';
$customer['dontSortMe'] = 'this value doesnt need to be sorted';
$customerSorted = array_replace(array_flip(array('name', 'dob', 'address')), $customer);
Результат:
Array (
[name] => Tim
[dob] => 12/08/1986
[address] => 123 fake st
[dontSortMe] => this value doesnt need to be sorted
)
Прекрасно работает со строковыми и цифровыми клавишами.
Ответ 4
function sortArrayByArray(array $toSort, array $sortByValuesAsKeys)
{
$commonKeysInOrder = array_intersect_key(array_flip($sortByValuesAsKeys), $toSort);
$commonKeysWithValue = array_intersect_key($toSort, $commonKeysInOrder);
$sorted = array_merge($commonKeysInOrder, $commonKeysWithValue);
return $sorted;
}
Ответ 5
Как насчет этого решения
$order = array(1,5,2,4,3,6);
$array = array(
1 => 'one',
2 => 'two',
3 => 'three',
4 => 'four',
5 => 'five',
6 => 'six'
);
uksort($array, function($key1, $key2) use ($order) {
return (array_search($key1, $order) > array_search($key2, $order));
});
Ответ 6
Возьмите один массив в качестве вашего заказа:
$order = array('north', 'east', 'south', 'west');
Вы можете отсортировать другой массив на основе значений, используя array_intersect
& shy; Docs:
/* sort by value: */
$array = array('south', 'west', 'north');
$sorted = array_intersect($order, $array);
print_r($sorted);
Или в вашем случае для сортировки по ключам используйте array_intersect_key
& shy; Docs:
/* sort by key: */
$array = array_flip($array);
$sorted = array_intersect_key(array_flip($order), $array);
print_r($sorted);
Обе функции сохраняют порядок первого параметра и возвращают значения (или ключи) только из второго массива.
Итак, для этих двух стандартных случаев вам не нужно писать функцию самостоятельно, чтобы выполнить сортировку/повторную компоновку.
Ответ 7
ЕСЛИ у вас есть массив в вашем массиве, вам придется немного приспособить функцию Эраном...
function sortArrayByArray($array,$orderArray) {
$ordered = array();
foreach($orderArray as $key => $value) {
if(array_key_exists($key,$array)) {
$ordered[$key] = $array[$key];
unset($array[$key]);
}
}
return $ordered + $array;
}
Ответ 8
Эта функция возвращает вспомогательный и отсортированный массив, основанный на втором параметре $keys
function array_sub_sort(array $values, array $keys){
$keys = array_flip($keys);
return array_merge(array_intersect_key($keys, $values), array_intersect_key($values, $keys));
}
Пример:
$array_complete = [
'a' => 1,
'c' => 3,
'd' => 4,
'e' => 5,
'b' => 2
];
$array_sub_sorted = array_sub_sort($array_complete, ['a', 'b', 'c']);//return ['a' => 1, 'b' => 2, 'c' => 3];
Ответ 9
Я использовал решение Darkwaltz4, но использовал array_fill_keys
вместо array_flip
, чтобы заполнить NULL
, если ключ не установлен в $array
.
$properOrderedArray = array_replace(array_fill_keys($keys, null), $array);
Ответ 10
Первое предложение
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 для создания массива порядка сортировки. Массив данных, который я сортировал, не нуждался в написании моей ассоциативной сортировки. Таким образом, слияние массива приведет к уничтожению массива данных. Оба являются отличными методами, и они должны быть заархивированы в любом наборе инструментов разработчиков. На основе ваших потребностей вы можете обнаружить, что вам действительно нужны обе концепции в ваших архивах.
Ответ 11
Я принял ответ от @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);
}
Ответ 12
У 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, когда не может найти совпадение, поэтому элементы, которые не находятся в массиве сортировки, естественно перемещаются в нижнюю часть массива.
Примечание: uasort() будет заказывать массив без влияния на отношения key = > value.
Ответ 13
- сортировать по запросу
- сохранить для int-keys (из-за 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;
}
Ответ 14
Немного поздно, но я не мог найти способ, которым я его реализовал, эта версия требует закрытия, 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' необходимо отсортировать и может показаться первым в примере