2008-12-08 6 views
109

Возможно ли в 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')); 

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

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

ответ

267

Просто используйте 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') 

пса - Я отвечаю на это «несвежий» вопрос, потому что я подумайте, что все циклы, указанные в предыдущих ответах, являются излишними.

89

Там вы идете:

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; 
} 
+11

Итак, вы можете присоединиться к 2 массивам со знаком +? Я никогда не знал этого, я использовал `array_merge()`! – alex 2009-09-24 23:08:39

+3

Это лучше, чем использование `usort()` или `uasort()`? – grantwparks 2009-09-25 19:57:08

+2

`foreach ($ orderArray as $ key => $ v)` сделал трюк для меня – 2011-09-26 02:06:06

21
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; 
} 
2

Если у вас есть массив в массиве, вам придется адаптировать функцию Эран немного ...

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; 
} 
13

Take один массив по вашему заказу:

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

Y ожно сортировать другой массив на основе значений, используя array_intersect­Docs:

/* sort by value: */ 
$array = array('south', 'west', 'north'); 
$sorted = array_intersect($order, $array); 
print_r($sorted); 

Или в вашем случае, сортировать по ключам, используйте array_intersect_key­Docs:

/* sort by key: */ 
$array = array_flip($array); 
$sorted = array_intersect_key(array_flip($order), $array); 
print_r($sorted); 

Обе функции будут поддерживать порядок первого параметра и будет возвращайте значения (или ключи) из второго массива.

Так что для этих двух стандартных случаев вам не нужно писать функцию самостоятельно, чтобы выполнить сортировку/переустановку.

0

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

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 для создания массива порядка сортировки. Массив данных, который я сортировал, не нуждался в написании моей ассоциативной сортировки. Таким образом, слияние массива приведет к уничтожению массива данных.Оба являются отличными методами, и они должны быть заархивированы в любом наборе инструментов разработчиков. На основе ваших потребностей вы можете найти, что вам действительно нужны обе концепции в ваших архивах.

0

Я принял ответ от @ 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 бы выполнил слияние в массиве [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); 
} 
33

Другой способ для 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 
) 

работает отлично со строковыми и цифровыми клавишами.

0

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.

23

Как об этом решении

$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)); 
}); 
-1

Немного поздно, но я не мог найти способ, которым я реализовал его, эта версия нуждается в закрытии, 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
  • рода по запросу
  • сохранить для int- ключи (из-за array_replace)
  • не возвращают ключи не существующие в inputArray
  • (по желанию) фильтр ключей не существующих в данном KeyList

Код:

/** 
* 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; 
} 
1

Эта функция возвращает к югу и отсортированный массив, основанный на второй параметр $ ключах

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]; 
1

Я использовал решение в Darkwaltz4, но используется array_fill_keys вместо array_flip, для заполнения NULL, если ключ не установлен в $array.

$properOrderedArray = array_replace(array_fill_keys($keys, null), $array); 
Смежные вопросы