2010-07-12 13 views
64

Estoy tratando de ordenar una matriz multidimensional por varias claves, y no tengo ni idea de dónde empezar. Miré uasort, pero no estaba muy seguro de cómo escribir una función para lo que necesito.ordenar matriz multidimensional por varias claves

Necesito ordenar por estado, luego tipo_evento, luego fecha.

Mi matriz tiene el siguiente aspecto:

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

... y quieres ordenar ¿cómo? – deceze

+0

posible duplicado de [Ordenar matriz multidimensional en PHP] (http://stackoverflow.com/questions/2059255/sorting-multidimensional-array-in-php) – outis

Respuesta

134

Usted necesita 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); 

A partir de PHP 5.5.0:

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

$mylist es ahora:

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

Gran uso de 'array_multisort()' que no sabía era posible. ¡Gracias! – damndaewoo

+0

tipo brillante. –

+0

@Rob Tengo mucha curiosidad sobre cómo ordenaría 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

Puedes hacerlo con usort. El argumento $cmp_function podría ser:

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

para un número arbitrario de campos en PHP 5.3, puede utilizar cierres para crear una función de comparación:

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

Para un número arbitrario de campos de diferentes tipos de 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

Podría simplificar bastante la anidación, y creo que tendrá que hacer algo más con la fecha, pero el enfoque parece ser el mejor hasta ahora. – deceze

+0

Lo bueno del formato '% Y-% m-% d' utilizado en la matriz de muestra es que la comparación de cadenas funciona para la comparación de fechas. – outis

3

he tratado de código y por debajo i éxito

código matriz

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

array llamada función de clasificación

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

matriz de clasificación 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; 
} 

si matriz inversa función de clasificación

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

Mejora en @Stijn código genio de leenknegt, aquí está mi 2 céntimos función pragmática:

$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

si desea ordenar en serie múltiple dimensional

primera matriz es:

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

segundo es:

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

esta matriz multidimensional que desea ordenar por orden descendente a la vez y luego use este código:

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