2010-07-12 1 views
64

Sto cercando di ordinare un array multidimensionale con più chiavi e non ho idea da dove iniziare. Ho guardato su uasort, ma non ero sicuro di come scrivere una funzione per quello di cui ho bisogno.Ordina array multidimensionale con più chiavi

Ho bisogno di ordinare per stato, quindi event_type, quindi data.

mio gamma si presenta così:

Array 
(
    [0] => Array 
     (
      [ID] => 1 
      [title] => Boring Meeting 
      [date_start] => 2010-07-30 
      [time_start] => 06:45:PM 
      [time_end] => 
      [state] => new-york 
      [event_type] => meeting 
     ) 

    [1] => Array 
     (
      [ID] => 2 
      [title] => Find My Stapler 
      [date_start] => 2010-07-22 
      [time_start] => 10:45:AM 
      [time_end] => 
      [state] => new-york 
      [event_type] => meeting 
     ) 

    [2] => Array 
     (
      [ID] => 3 
      [title] => Mario Party 
      [date_start] => 2010-07-22 
      [time_start] => 02:30:PM 
      [time_end] => 07:15:PM 
      [state] => new-york 
      [event_type] => party 
     ) 

    [3] => Array 
     (
      [ID] => 4 
      [title] => Duct Tape Party 
      [date_start] => 2010-07-28 
      [time_start] => 01:00:PM 
      [time_end] => 
      [state] => california 
      [event_type] => party 
     ) 
...... etc 
+1

... e si desidera ordinare come? – deceze

+0

possibile duplicato di [Ordinamento array multidimensionale in PHP] (http://stackoverflow.com/questions/2059255/sorting-multidimensional-array-in-php) – outis

risposta

134

È necessario array_multisort

$mylist = array(
    array('ID' => 1, 'title' => 'Boring Meeting', 'event_type' => 'meeting'), 
    array('ID' => 2, 'title' => 'Find My Stapler', 'event_type' => 'meeting'), 
    array('ID' => 3, 'title' => 'Mario Party', 'event_type' => 'party'), 
    array('ID' => 4, 'title' => 'Duct Tape Party', 'event_type' => 'party') 
); 

# get a list of sort columns and their data to pass to array_multisort 
$sort = array(); 
foreach($mylist as $k=>$v) { 
    $sort['title'][$k] = $v['title']; 
    $sort['event_type'][$k] = $v['event_type']; 
} 
# sort by event_type desc and then title asc 
array_multisort($sort['event_type'], SORT_DESC, $sort['title'], SORT_ASC,$mylist); 

Dal PHP 5.5.0:

array_multisort(array_column($mylist, 'event_type'), SORT_DESC, 
       array_column($mylist, 'title'),  SORT_ASC, 
       $mylist); 

$mylist è ora:

array (
    0 => 
    array (
    'ID' => 4, 
    'title' => 'Duct Tape Party', 
    'event_type' => 'party', 
), 
    1 => 
    array (
    'ID' => 3, 
    'title' => 'Mario Party', 
    'event_type' => 'party', 
), 
    2 => 
    array (
    'ID' => 1, 
    'title' => 'Boring Meeting', 
    'event_type' => 'meeting', 
), 
    3 => 
    array (
    'ID' => 2, 
    'title' => 'Find My Stapler', 
    'event_type' => 'meeting', 
), 
) 
+0

Grande uso di 'array_multisort()' che non sapevo fosse possibile. Grazie! – damndaewoo

+0

Un ragazzo brillante. –

+0

@Rob Sono molto curioso di come ordinare date_start – frazras

3
class Sort { 
    private $actual_order = 'asc'; 
    private $actual_field = null; 

    public function compare_arrays($array1, $array2) { 

     if ($array1[$this->actual_field] == $array2[$this->actual_field]) { 
      return 0; 
     } 
     elseif ($array1[$this->actual_field] > $array2[$this->actual_field]) { 
      return ($this->actual_order == 'asc' ? 1 : -1); 
     } 
     else { 
      return ($this->actual_order == 'asc' ? -1 : 1); 
     } 

    } 


    public function order_array(&$array) { 

     usort($array, array($this, 'compare_arrays')); 

    } 


    public function __construct ($field, $actual_order = 'asc') { 
     $this->actual_field = $field; 
     $this->actual_order = $actual_order; 
    } 

} 

// use 

$sort = new Sort ("state"); 

$sort->order_array($array); 
12

È possibile farlo con usort. L'argomento $cmp_function potrebbe essere:

function my_sorter($a, $b) { 
    $c = strcmp($a['state'], $b['state']); 
    if($c != 0) { 
     return $c; 
    } 

    $c = strcmp($a['event_type'], $b['event_type']); 
    if($c != 0) { 
     return $c; 
    } 

    return strcmp($a['date_start'], $b['date_start']); 
} 

Per un numero arbitrario di campi in PHP 5.3, è possibile utilizzare le chiusure per creare una funzione di confronto:

function make_cmp($fields, $fieldcmp='strcmp') { 
    return function ($a, $b) use (&$fields) { 
     foreach ($fields as $field) { 
      $diff = $fieldcmp($a[$field], $b[$field]); 
      if($diff != 0) { 
       return $diff; 
      } 
     } 
     return 0; 
    } 
} 

usort($arr, make_cmp(array('state', 'event_type', 'date_start'))) 

Per un numero arbitrario di campi di tipi diversi in PHP 5.3:

function make_cmp($fields, $dfltcmp='strcmp') { 
    # assign array in case $fields has no elements 
    $fieldcmps = array(); 
    # assign a comparison function to fields that aren't given one 
    foreach ($fields as $field => $cmp) { 
     if (is_int($field) && ! is_callable($cmp)) { 
      $field = $cmp; 
      $cmp = $dfltcmp; 
     } 
     $fieldcmps[$field] = $cmp; 
    } 
    return function ($a, $b) use (&$fieldcmps) { 
     foreach ($fieldcmps as $field => $cmp) { 
      $diff = call_user_func($cmp, $a[$field], $b[$field]); 
      if($diff != 0) { 
       return $diff; 
      } 
     } 
     return 0; 
    } 
} 

function numcmp($a, $b) { 
    return $a - $b; 
} 
function datecmp($a, $b) { 
    return strtotime($a) - strtotime($b); 
} 
/** 
* Higher priority come first; a priority of 2 comes before 1. 
*/ 
function make_evt_prio_cmp($priorities, $default_priority) { 
    return function($a, $b) use (&$priorities) { 
     if (isset($priorities[$a])) { 
      $prio_a = $priorities[$a]; 
     } else { 
      $prio_a = $default_priority; 
     } 
     if (isset($priorities[$b])) { 
      $prio_b = $priorities[$b]; 
     } else { 
      $prio_b = $default_priority; 
     } 
     return $prio_b - $prio_a; 
    }; 
} 

$event_priority_cmp = make_evt_prio_cmp(
    array('meeting' => 5, 'party' => 10, 'concert' => 7), 
    0); 

usort($arr, make_cmp(array('state', 'event' => $event_priority_cmp, 'date_start' => 'datecmp', 'id' => 'numcmp'))) 
+1

Potresti semplificare un po 'il nesting e penso che dovrai fare qualcosa di più con la data, ma l'approccio sembra il migliore finora. – deceze

+0

Il bello del formato '% Y-% m-% d' utilizzato nell'array campione è il confronto delle stringhe per il confronto delle date. – outis

3

ho cercato di seguito il codice e ho successo

codice matrice

$songs = array(
     '1' => array('artist'=>'Smashing Pumpkins', 'songname'=>'Soma'), 
     '2' => array('artist'=>'The Decemberists', 'songname'=>'The Island'), 
     '3' => array('artist'=>'Fleetwood Mac', 'songname' =>'Second-hand News') 
); 

matrice chiamata classificare funzione

$songs = subval_sort($songs,'artist'); 
print_r($songs); 

matrice classificare Funcation

function subval_sort($a,$subkey) { 
    foreach($a as $k=>$v) { 
     $b[$k] = strtolower($v[$subkey]); 
    } 
    asort($b); 
    foreach($b as $key=>$val) { 
     $c[] = $a[$key]; 
    } 
    return $c; 
} 

se matrice inversa funzione di ordinamento

function subval_sort($a,$subkey) { 
     foreach($a as $k=>$v) { 
      $b[$k] = strtolower($v[$subkey]); 
     } 
     arsort($b); 
     foreach($b as $key=>$val) { 
      $c[] = $a[$key]; 
     } 
     return $c; 
    } 
1

migliorando @Stijn Codice genio di Leenknegt, ecco la mia 2 cent funzione pragmatica:

$data[] = array('volume' => 67, 'edition' => 2); 
$data[] = array('volume' => 86, 'edition' => 1); 
$data[] = array('volume' => 85, 'edition' => 6); 
$data[] = array('volume' => 98, 'edition' => 2); 
$data[] = array('volume' => 86, 'edition' => 6); 
$data[] = array('volume' => 67, 'edition' => 7); 

function make_cmp(array $sortValues) 
{ 
    return function ($a, $b) use (&$sortValues) { 
     foreach ($sortValues as $column => $sortDir) { 
      $diff = strcmp($a[$column], $b[$column]); 
      if ($diff !== 0) { 
       if ('asc' === $sortDir) { 
        return $diff; 
       } 
       return $diff * -1; 
      } 
     } 
     return 0; 
    }; 
} 

usort($data, make_cmp(['volume' => "desc", 'edition' => "asc"])); 
0

se si desidera ordinare più di matrice tridimensionale

primo array è:

$results['total_quote_sales_person_wise']['quote_po']; 

seconda è:

$results['total_quote_sales_person_wise']['quote_count']; 

questo array multidimentale si desidera ordinare in ordine decrescente in una volta quindi utilizzare questo codice:

array_multisort($results['total_quote_sales_person_wise']['quote_po'],SORT_DESC, $results['total_quote_sales_person_wise']['quote_count'],SORT_DESC);