webentwicklung-frage-antwort-db.com.de

Ein Array nach Schlüsseln basierend auf einem anderen Array sortieren?

Kann man in PHP so etwas tun? Wie würdest du eine Funktion schreiben? Hier ist ein Beispiel. Die Reihenfolge ist das Wichtigste.

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

Und ich würde gerne etwas tun 

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

Weil ich am Ende ein foreach () benutze und sie nicht in der richtigen Reihenfolge sind (weil ich die Werte an einen String anhange, der in der richtigen Reihenfolge sein muss und ich nicht alle Array-Schlüssel im Voraus kenne/Werte).

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

121
alex

Verwenden Sie einfach array_merge oder array_replace. Array_merge funktioniert, indem Sie mit dem von Ihnen angegebenen Array (in der richtigen Reihenfolge) beginnen und die Schlüssel mit Daten aus Ihrem tatsächlichen Array überschreiben/hinzufügen:

$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 beantworte diese "veraltete" Frage, weil ich denke, dass alle Schleifen, die als vorherige Antworten gegeben wurden, übertrieben wirken.

298
Darkwaltz4

Da gehst du hin:

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;
}
95
Eran Galperin

Ein anderer Weg 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
)

Funktioniert gut mit String- und Zifferntasten.

34
ekuser

Wie wäre es mit dieser 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));
});
30
Peter de Groot
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;
}
22
OIS

Nimm ein Array als Bestellung:

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

Sie können ein anderes Array nach Werten sortieren, indem Sie array_intersect verwenden.Docs :

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

Oder verwenden Sie in Ihrem Fall array_intersect_key, um nach Schlüsseln zu sortieren.Docs :

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

Beide Funktionen behalten die Reihenfolge des ersten Parameters bei und geben nur die Werte (oder Schlüssel) aus dem zweiten Array zurück.

Für diese beiden Standardfälle müssen Sie also nicht selbst eine Funktion schreiben, um die Sortierung/Neuanordnung durchzuführen.

14
hakre

Ich habe die Darkwaltz4-Lösung verwendet, aber array_fill_keys anstelle von array_flip verwendet, um mit NULL zu füllen, wenn in $array kein Schlüssel festgelegt ist.

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

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

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

Ohne Magie ...

$array=array(28=>c,4=>b,5=>a);
$seq=array(5,4,28);    
SortByKeyList($array,$seq) result: array(5=>a,4=>b,28=>c);

function sortByKeyList($array,$seq){
    $ret=array();
    if(empty($array) || empty($seq)) return false;
    foreach($seq as $key){$ret[$key]=$dataset[$key];}
    return $ret;
}
2
Jenovai Matyas

Diese Funktion gibt ein untergeordnetes und sortiertes Array zurück, das auf dem zweiten Parameter $ keys basiert

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:

$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
Doglas

PHP bietet Funktionen, die Ihnen dabei helfen:

$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 erledigt die ganze Arbeit für Sie und array_search liefert die Schlüssel. array_search () gibt false zurück, wenn keine Übereinstimmung gefunden wird, sodass Elemente, die sich nicht im Sortierarray befinden, natürlich zum unteren Ende des Arrays verschoben werden.

Hinweis: uasort () ordnet das Array an, ohne die Schlüssel-Wert-Beziehungen zu beeinflussen.

0
danielcraigie
  • art wie gewünscht
  • speichern für int-keys (wegen array_replace)
  • keine return-Schlüssel sind in inputArray nicht vorhanden
  • (optional) Filterschlüssel nicht in der angegebenen Schlüsselliste vorhanden

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

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 möchte darauf hinweisen, dass beide Vorschläge großartig sind. 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 beim Zusammenführen/Flip des Arrays tatsächlich das andere assoziative Array zusammengeführt und überschrieben. In meinem Fall sind das nicht die Ergebnisse, nach denen ich gesucht habe. Ich habe eine settings.ini-Datei verwendet, um mein Sortierreihenfolge-Array zu erstellen. Das Datenarray, das ich sortierte, musste von meinem assoziativen Sortierpartner nicht überschrieben werden. Dadurch würde das Zusammenführen von Arrays mein Datenarray zerstören. Beide Methoden sind großartig, beide müssen in jeder Entwickler-Toolbox archiviert werden. Je nach Ihren Bedürfnissen benötigen Sie möglicherweise beide Konzepte in Ihren Archiven.

0
user1653711

Ich habe die Antwort von @ Darkwaltz4 aus Gründen der Kürze angenommen und möchte mitteilen, wie ich die Lösung an Situationen angepasst habe, in denen das Array für jede Iteration unterschiedliche Schlüssel enthalten kann:

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 pflegte einen "Hauptschlüssel" wie folgt:

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

array_merge hätte die Zusammenführung in der Array [1] - Iteration basierend auf $ master_key ausgeführt und ['some_key'] = '' für diese Iteration einen leeren Wert erzeugt. Daher wurde array_intersect_key verwendet, um $ master_key in jeder Iteration wie folgt zu ändern:

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