2010-02-17 2 views
16

Ho un array di chiavi stringa con valori numerici per l'uso in un elenco di tag con il numero di occorrenze di ogni tag, quindi:Ordinamento multiplo di array PHP: valore per tasto?

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

questo è così posso visualizzare l'elenco tag decrescente occurance ordine così:

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

posso usare arsort per invertire ordina dal valore che è brillante ma voglio anche i tag che hanno lo stesso valore numerico visualizzare in ordine alfabetico, quindi il risultato finale può essere:

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

c'è un modo per farlo? Sto indovinando che usort potrebbe essere la strada da percorrere ma guardo gli esempi su php.net ei miei occhi si glassano! grazie molto!!!

risposta

12

Dai un'occhiata alla esempi # 3: http://php.net/manual/en/function.array-multisort.php

È necessario creare due array da utilizzare come indici; uno composto dalle chiavi dell'array originale e l'altro dai valori dell'array originale.

Quindi utilizzare il multisort per ordinare i valori di testo (tasti dell'array originale) e quindi i valori numerici (valori dell'array originale).

+3

@MMior Quindi qual è la soluzione non complicata? –

+1

vedere @Jon Bernhardt qui sotto per un buon esempio di implementazione. –

0

Non l'ho provato, ma hai provato a ordinare prima i tasti in ordine crescente, quindi a ordinare i valori in ordine decrescente?

Sembra che la maggior parte dei tipi non spostino gli elementi se sono già gli stessi.

0

È possibile creare semplicemente una funzione per creare un array vuoto e inserirli in ordine in base ai confronti.

0

stai pensando troppo complicato:

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

Ora l'array è ordinato come si desidera.

+0

Stavo per pubblicare questa risposta esatta. Comunque, ho provato e posso confermare che funziona. I tipi di php –

+3

non sono stabili, quindi non è garantito che funzioni. http://www.php.net/manual/en/array.sorting.php – goat

+0

@chris, è vero, ma non ho ancora trovato casi in cui non avrebbe funzionato, quindi continuerei con questo. –

13

RISOLTO

Dopo un po 'di sperimentazione ho scoperto che array_multisort fa egregiamente:

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

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

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

:)

+2

Questa sarebbe la risposta di SlappyTheFish, giusto? Penso che dovresti contrassegnare quella risposta come accettata e poi guardare le funzioni array_keys() e array_values ​​() per sbarazzarti del tuo ciclo. –

+2

Anche una nota per i futuri visitatori: '$ tag = array_keys ($ arrTags); $ num = array_values ​​($ arrTags); 'formerebbe gli array identici senza un loop. – nickb

+0

Perché questo non funziona per me? Copio il campione sopra e la soluzione ha ottenuto lo stesso risultato nella domanda. –

2

SlappyTheFish è corretto Re: usando array_multisort vs ksort, arsort

Nell'esempio di David ksort, arsort funziona bene, tuttavia se il ke I valori stringa ys contengono caratteri diversi da caratteri alfabetici, l'ordinamento potrebbe non funzionare come previsto.

ex:

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

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

print_r($arrTags); 

rendimenti:

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

tuttavia utilizzando:

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

restituisce:

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

Come suggerisce Scott Saunders nel suo commento alla soluzione di David, è possibile utilizzare le funzioni array_keys() e array_values ​​() per sbarazzarsi del ciclo. In realtà, si può risolvere questo in una sola riga di codice:

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

Grazie per questo codice. Ho la situazione esatta come la domanda originale e questo funziona per me. Quello che mi dà fastidio è che non sono esattamente sicuro di quello che sta succedendo qui. Qual è la funzione dell'ultimo parametro? Posso vedere che l'ultimo parametro (passato per riferimento) è l'unica possibilità per restituire l'array modificato, OK. Ma in che modo gli array sono correlati tra loro? Quando il multisort fa il suo lavoro andando da sinistra a destra sono gli array successivi ordinati insieme a loro. In tal caso, tutti gli array devono avere la stessa lunghezza che non è richiesta dalla documentazione.#confused – andypotter

+0

@andypotter: in sostanza, 'array_multi_sort()' creerà internamente un altro array '$ indiretto 'dove ogni indice è un array contenente tutti i valori degli array forniti:' $ indiretto [$ i] = [$ v1, $ v2, $ v3, ..., NULL] '. Quindi QuickSort viene applicato all'array utilizzando una funzione di confronto speciale che prima confronterà '$ indir [$ a] [$ r]' a '$ indiretto [$ b] [$ r]' dove '$ r == 0' se sono uguali, '$ r' viene aumentato finché' $ indiretto [$ a] [$ r] 'è' null' (sono state utilizzate tutte le matrici fornite). Alla fine ogni array viene riscritto secondo '$ indiretto'. Se si utilizzano array di dimensioni diverse, viene restituito FALSE. – 2072

+0

Brillante - grazie Jon! – Martin

5

La soluzione proposta precedente sembra logico, ma semplicemente doens't lavoro:

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

Il codice PHP completo per realizzare il richiesto Ordinamento, sarà:

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

prega di notare che array_multisort() utilizza riferimenti su input dell'utente, quindi dovrete utilizzare due variabels temporanee ($ k e $ v) per la fornitura di contenuti come input da parte dell'utente. In questo modo array_multisort() può modificare il contenuto. Successivamente, ricostruire l'array ordinato tramite array_combine().

Ho costruito una funzione riutilizzabili per eseguire questa operazione:

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

Deve essere ok.