2010-02-17 2 views
16

Ich habe ein Array von String-Schlüssel mit numerischen Werten für die Verwendung in einer Liste von Tags mit der Anzahl der Vorkommen jeden Tags, also:PHP-Array mehrfache Sortierung - nach Wert, dann nach Schlüssel?

$arrTags['mango'] = 2; 
$arrTags['orange'] = 4; 
$arrTags['apple'] = 2; 
$arrTags['banana'] = 3; 

dies ist, so kann ich in absteigenden Vorkommen, um die Tag-Liste angezeigt also:

orange (4) 
banana (3) 
mango (2) 
apple (2) 

i arsort sortiert nach dem Wert verwenden kann zu umkehren, die brillant ist, aber ich möchte auch alle Tags, die den gleichen Zahlenwert haben alphabetisch sortiert werden, so dass das Endergebnis kann sein:

Gibt es eine Möglichkeit, das kann ich tun? Ich nehme an, dass Usort vielleicht der Weg zu gehen ist, aber ich schaue auf die Beispiele auf php.net und meine Augen glasieren über! Danke vielmals!!!

Antwort

12

Hier finden Sie aktuelle Beispiele # 3: http://php.net/manual/en/function.array-multisort.php

Sie müssen zwei Arrays erstellen, wie Indizes zu verwenden; eine besteht aus den Schlüsseln des ursprünglichen Arrays und den anderen Werten des ursprünglichen Arrays.

Verwenden Sie dann Multisort, um nach Textwerten (Schlüssel des ursprünglichen Arrays) und dann nach den numerischen Werten (Werte des ursprünglichen Arrays) zu sortieren.

+3

@MMior Was ist also die nicht komplizierte Lösung? –

+1

siehe @Jon Bernhardt brüllen für ein schönes Implementierungsbeispiel. –

0

Ich habe es nicht versucht, aber haben Sie versucht, die Schlüssel zuerst aufsteigend sortieren, dann die Werte absteigend sortieren?

Es scheint, dass die meisten Arten Elemente nicht verschieben, wenn sie bereits gleich sind.

0

Sie können einfach eine Funktion erstellen, um ein leeres Array zu erstellen und sie basierend auf Vergleichen in der Reihenfolge einzufügen.

0

Sie denken zu kompliziert:

ksort($arrTags); 
arsort($arrTags); 

Jetzt Ihr Array sortiert ist, wie Sie es wollen.

+0

Ich wollte gerade diese genaue Antwort posten. Wie auch immer, versuchte es und ich kann bestätigen, dass es funktioniert. –

+3

PHP-Sortierungen sind nicht stabil, so dass Sie nicht garantieren können, dass dies funktioniert. http://www.php.net/manual/en/array.sorting.php – goat

+0

@chris, das ist wahr, aber ich habe immer noch keine Fälle gefunden, wo es nicht funktionieren würde, also würde ich damit fortfahren. –

13

GELÖST

Nach ein wenig Experimentieren entdeckte ich, dass array_multisort der Trick schön:

$tag = array(); 
$num = array(); 

foreach($arrTags as $key => $value){ 
$tag[] = $key; 
$num[] = $value; 
} 

array_multisort($num, SORT_DESC, $tag, SORT_ASC, $arrTags); 

:)

+2

Das wäre die Antwort von SlappyTheFish, oder? Ich denke, du solltest diese Antwort als akzeptiert markieren und dann die Funktionen array_keys() und array_values ​​() betrachten, um deine Schleife loszuwerden. –

+2

Auch ein Hinweis für zukünftige Besucher: '$ tag = array_keys ($ arrTags); $ num = array_values ​​($ arrTags); 'würde die identischen Arrays ohne eine Schleife bilden. – nickb

+0

Warum funktioniert das nicht für mich? Ich kopiere das obige Beispiel und die Lösung habe gerade das gleiche Ergebnis in der Frage. –

2

SlappyTheFish korrekte Re ist: mit array_multisort gegen ksort, arsort

In Davids Beispiel ksort, arsort funktioniert gut, aber wenn die Ke Die Zeichenfolgenwerte von ys enthalten andere Zeichen als alphabetische Zeichen. Die Sortierung funktioniert möglicherweise nicht wie gewünscht.

ex:

$arrTags['banana'] = 3; 
$arrTags['mango'] = 2; 
$arrTags['apple1'] = 2; 
$arrTags['orange'] = 4; 
$arrTags['almond1'] = 2; 

ksort($arrTags); 
arsort($arrTags); 

print_r($arrTags); 

kehrt:

Array 
(
    [orange] => 4 
    [banana] => 3 
    [apple1] => 2 
    [mango] => 2 
    [almond1] => 2 
) 

jedoch mit:

$arrTags['banana'] = 3; 
$arrTags['mango'] = 2; 
$arrTags['apple1'] = 2; 
$arrTags['orange'] = 4; 
$arrTags['almond1'] = 2; 

$tag = array(); 
$num = array(); 

foreach($arrTags as $key => $value){ 
    $tag[] = $key; 
    $num[] = $value; 
} 

array_multisort($num, SORT_DESC, $tag, SORT_ASC, $arrTags); 


print_r($arrTags); 

kehrt:

Array 
(
    [orange] => 4 
    [banana] => 3 
    [almond1] => 2 
    [apple1] => 2 
    [mango] => 2 
) 
28

Wie Scott Saunders in seinem Kommentar zu Davids Lösung andeutet, können Sie mit den Funktionen array_keys() und array_values ​​() die Schleife loswerden. In der Tat, können Sie dies in einer Zeile Code lösen:

array_multisort(array_values($arrTags), SORT_DESC, array_keys($arrTags), SORT_ASC, $arrTags); 
+0

Danke für diesen Code. Ich habe die genaue Situation als die ursprüngliche Frage und das funktioniert für mich. Was mich stört ist, dass ich nicht genau weiß, was hier passiert. Welche Funktion hat der letzte Parameter? Ich kann sehen, dass der letzte Parameter (der durch Verweis übergeben wird) die einzige Möglichkeit ist, das geänderte Array zurückzugeben, OK. Aber wie sind die Array-Sets aufeinander bezogen? Wenn Multisort von links nach rechts arbeitet, werden die nachfolgenden Arrays mit ihnen sortiert. Wenn dies der Fall ist, müssen alle Arrays die gleiche Länge haben, die von der Dokumentation nicht benötigt wird.#confused – andypotter

+0

@andypotter: Im Grunde erstellt 'array_multi_sort()' intern ein anderes Array '$ indirect', wobei jeder Index ein Array ist, das alle Werte der angegebenen Arrays enthält:' $ indirect [$ i] = [$ v1, $ v2, $ v3, ..., NULL] '. Dann wird QuickSort mit einer speziellen Vergleichsfunktion auf das Array angewendet, die zuerst $ indirect [$ a] [$ r] 'mit $ indirect [$ b] [$ r]' vergleicht, wobei '$ r == 0 if Sie sind gleich, "$ r" wird erhöht bis "$ indirect [$ a] [$ r]' 'null' ist (alle bereitgestellten Arrays wurden verwendet). Schließlich wird jedes Array nach '$ indirekt 'neu geschrieben. Wenn Sie Arrays unterschiedlicher Größe verwenden, wird FALSE zurückgegeben. – 2072

+0

Brilliant - danke Jon! – Martin

5

Die bisherige vorgeschlagene Lösung erscheint logisch, aber es doens't nur Arbeit:

ksort($arrTags); 
arsort($arrTags); 

Der komplette PHP-Code zu erkennen, die gefragt Sortieren, wird sein:

$k = array_keys($arrTags); 
$v = array_values($arrTags); 
array_multisort($k, SORT_ASC, $v, SORT_DESC); 
$arrTags = array_combine($k, $v); 

Sie bitte, dass array_multisort beachten() verwendet Verweise auf Benutzereingaben, so dass Sie zwei temporäre variabels ($ k und $ v) verwenden, um Inhalte als Benutzereingaben zu liefern. Auf diese Weise kann array_multisort() den Inhalt ändern. Erstellen Sie später das sortierte Array über array_combine() neu.

Ich habe eine wiederverwendbare Funktion gebaut diese Aufgabe zu erfüllen:

<?php 
/** 
* Sort a multi-dimensional array by key, then by value. 
* 
* @param array Array to be sorted 
* @param int One of the available sort options: SORT_ASC, SORT_DESC, SORT_REGULAR, SORT_NUMERIC, SORT_STRING 
* @param int One of the available sort options: SORT_ASC, SORT_DESC, SORT_REGULAR, SORT_NUMERIC, SORT_STRING 
* @return void 
* @example The following array will be reordered: 
* $a = array(
*  'd' => 4, 
*  'c' => 2, 
*  'a' => 3, 
*  'b' => 1, 
*  'e' => 2, 
*  'g' => 2, 
*  'f' => 2, 
* ); 
* SortArrayByKeyThanValue($a);  # reorder array to: array(
*  'b' => 1, 
*  'c' => 2, 
*  'e' => 2, 
*  'f' => 2, 
*  'g' => 2, 
*  'a' => 3, 
*  'd' => 4, 
* ); 
* @author Sijmen Ruwhof <sijmen(a)secundity.com> 
* @copyright 2011, Secundity 
*/ 
function SortArrayByKeyThanValue (&$pArray, $pSortMethodForKey = SORT_ASC, $pSortMethodForValue = SORT_ASC) 
{ 
    # check user input: sorting is not necessary 
    if (count($pArray) < 2) 
     return; 

    # define $k and $v as array_multisort() needs real variables, as user input is put by reference 
    $k = array_keys ($pArray); 
    $v = array_values($pArray); 

    array_multisort(
     $v, $pSortMethodForValue, 
     $k, $pSortMethodForKey 
    ); 
    $pArray = array_combine($k, $v); 
} 
?> 
0
//preserve arrays keys for later use 
$ar1= array_keys($your_array); 

//preserve array's values for later use 
$ar2= array_values($your_array); 

//perform sorting by value and then by key 
array_multisort($ar2, SORT_DESC, $ar1, SORT_DESC); 

//combine sorted values and keys arrays to new array 
$sorted_array = array_combine($ar1, $ar2); 

ok sein muss.