2008-12-08 15 views
109

Ist es in PHP möglich, so etwas zu tun? Wie würdest du eine Funktion schreiben? Hier ist ein Beispiel. Die Reihenfolge ist das Wichtigste.Sortiert ein Array nach Schlüsseln, die auf einem anderen Array basieren?

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

Und ich möchte so etwas wie

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

tun, weil am Ende ich ein foreach() und sie sind nicht in der richtigen Reihenfolge (weil ich die Werte an eine anhängen String, der in der richtigen Reihenfolge sein muss und ich kenne nicht alle Array-Schlüssel/Werte im Voraus.

Ich habe die internen Array-Funktionen von PHP durchgesehen, aber es scheint, dass Sie nur alphabetisch oder numerisch sortieren können.

Antwort

267

Verwenden Sie einfach array_merge oder array_replace. Array_merge Arbeiten mit dem Array starten Sie es geben (in der richtigen Reihenfolge) und Überschreiben/Hinzufügen der Schlüssel mit Daten aus Ihrem aktuellen Array:

$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 - ich diesen ‚abgestanden‘ Frage ich zu antworten, weil ich denke, dass alle Schleifen, die als vorherige Antworten gegeben werden, übertrieben sind.

+22

Es funktioniert gut, wenn Sie String-Tasten haben, aber nicht für die numerische Taste. PHP Docs: "Wenn die Eingabearrays die gleichen Zeichenfolgenschlüssel haben, überschreibt der spätere Wert für diesen Schlüssel den vorherigen. Wenn jedoch die Arrays numerische Schlüssel enthalten, überschreibt der spätere Wert nicht den ursprünglichen Wert, sondern wird angehängt. " – bolbol

+3

Schön, aber was, wenn die Schlüssel nicht in den Werten existieren? Ich brauche das, aber nur, wenn einer der Schlüssel existiert ... Wahrscheinlich brauche ich eine foreach dann ... –

+4

für meinen Fall ist es array_replace anstelle von array_merge. array_merge kombiniert beide Werte, anstatt das zweite Array in die geordneten Schlüssel zu ersetzen. – neofreko

89

Dort gehen Sie:

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

Sie können also 2 Arrays mit einem + Zeichen verbinden? Ich wusste das nie, ich habe 'array_merge()'! – alex

+3

Ist das besser als mit 'usort()' oder 'uasort()'? – grantwparks

+2

'foreach ($ orderArray als $ key => $ v)' hat den Trick für mich gemacht –

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

WENN Sie Array im Array haben, werden Sie die Funktion von Eran ein wenig anpassen müssen ...

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

Nehmen ein Array als Ihre Bestellung:

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

Y ou kann ein anderes Array sortieren basierend auf Werten array_intersect­Docs:

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

Oder in Ihrem Fall durch Tasten zu sortieren, verwenden array_intersect_key­Docs:

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

Beide Funktionen die Reihenfolge des ersten Parameters halten und wird Geben Sie nur die Werte (oder Schlüssel) aus dem zweiten Array zurück.

Für diese beiden Standardfälle müssen Sie keine eigene Funktion schreiben, um das Sortieren/Neuanordnen durchzuführen.

+0

Der Schnittpunkt würde jene Einträge loswerden, die er nicht im Voraus kennt. – DanMan

+1

Dies ist falsch für die Sortierung nach Schlüsseln. array_intersect_key gibt nur die Werte von array1 zurück, nicht array2 – pavsid

+0

Mit pavsid abgestimmt - das Argument array_intersect_key ist falsch - es gibt die Werte aus dem ersten Array zurück, nicht aus dem zweiten. –

0

erster Vorschlag

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

zweiter Vorschlag

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

Ich wollte darauf hinweisen, dass diese beiden Vorschläge sind genial. Sie sind jedoch Äpfel und Orangen. Der Unterschied? Einer ist nicht assoziativ freundlich und der andere ist assoziativ freundlich. Wenn Sie zwei vollständig assoziative Arrays verwenden, wird das Array merge/flip tatsächlich zusammengeführt und überschreibt das andere assoziative Array. In meinem Fall sind das nicht die Ergebnisse, nach denen ich gesucht habe. Ich habe eine settings.ini-Datei verwendet, um meine Sortierreihenfolge zu erstellen. Das Daten-Array, das ich sortiert hatte, musste nicht von meinem assoziativen Sortier-Counter geschrieben werden. Das Zusammenführen von Arrays würde also mein Datenarray zerstören.Beide sind großartige Methoden, beide müssen in jeder Entwickler-Toolbox archiviert werden. Je nach Ihren Bedürfnissen finden Sie möglicherweise beide Konzepte in Ihren Archiven.

0

angenommen ich die Antwort von @ Darkwaltz4 für seine Kürze und mag, wie ich die Lösung für Situationen angepasst teilen, wo das Array verschiedene Schlüssel für jede Iteration wie so enthält:

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'; 

und gepflegt ein " Hauptschlüssel“wie folgt:

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

array_merge hätte die Zusammenführung im Array [1] Iteration basierend auf $ master_key und produziert [ 'some_key'] = '', einen leeren Wert, für diese Iteration ausgeführt. Daher wurde array_intersect_key verwendet $ master_key in jeder Iterationen zu modifizieren, etwa so:

foreach ($customer as $customer) { 
    $modified_key = array_intersect_key($master_key, $unordered_array); 
    $properOrderedArray = array_merge($modified_key, $customer); 
} 
33

Eine weitere Möglichkeit für 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); 

Ergebnis:

Array (
    [name] => Tim 
    [dob] => 12/08/1986 
    [address] => 123 fake st 
    [dontSortMe] => this value doesnt need to be sorted 
) 

Adaequat mit Zeichenfolge und numerischen Tasten.

+1

+ Während beide arbeiten, fand ich 'array_replace()', um die Absicht besser zu vermitteln als 'array_merge()'. –

+0

'Array_replace' lässt auch den Variablentyp intakt. Wenn einer der Werte in Ihrem Array '(String) '1'' wäre und Sie den Operator' + 'verwendet hätten, wäre der Wert in' (int) 1' umgewandelt worden. –

+0

Dies funktioniert auch bei numeric keys ('array_merge()' würde sie einfach anhängen?). Die Logik ist sehr gut erklärt [hier] (https://www.designcise.com/web/tutorial/how-to-sort-an-array-by-keys-based-on-order-in-a-sekundär- Array-in-PHP). * First *, 'array_flip()' ändert die Werte des $ order-Arrays in Schlüssel. * Second *, 'array_replace()' ersetzt die Werte des ersten Arrays durch Werte mit denselben Schlüsseln im zweiten Array. Wenn Sie ein Array nach Schlüsseln aus einem anderen sortieren müssen, müssen Sie nicht einmal 'array_flip' verwenden. –

0

PHP hat Funktionen, die Sie mit diesem helfen: Sie

$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 macht die ganze Arbeit und array_search bietet die Schlüssel. array_search() gibt false zurück, wenn keine Übereinstimmung gefunden werden kann, sodass Elemente, die nicht im Sortierarray enthalten sind, sich natürlich am Ende des Arrays befinden.

Hinweis: uasort() ordnet das Array an, ohne die Beziehung key => value zu beeinflussen.

23

Wie über diese Lösung

$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

Ein bisschen spät, aber ich konnte die Art, wie ich es implementiert nicht finden, diese Version benötigt Schließung, PHP> = 5.3, aber geändert werden könnte nicht:

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

Natürlich ‚dontSortMe‘ out werden muss sortiert und können zuerst im Beispiel

0
  • Art erscheinen als
  • angeforderte
  • speichern für int- Tasten (wegen array_replace)
  • Schlüssel nicht zurückgeben existieren nicht in inputArray
  • (optional) Filterschlüssel nicht in der gegebenen vorhandenen keyList

Code:

/** 
* 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

Diese Funktion

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

Beispiel ein Unter und sortierten Feld basierend auf dem zweiten Parameter $ Schlüssel zurück:

$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

Ich benutzte die Darkwaltz4-Lösung, sondern verwendet array_fill_keys statt array_flip, mitfüllen, wenn ein Schlüssel nicht in $array gesetzt ist.

$properOrderedArray = array_replace(array_fill_keys($keys, null), $array); 
Verwandte Themen