J'essaie de trier un tableau multidimensionnel en fonction de plusieurs clés et je ne sais pas par où commencer. J'ai regardé uasort, mais je ne savais pas trop comment écrire une fonction pour ce dont j'avais besoin.
J'ai besoin de trier par l'état, puis event_type, puis la date.
Mon tableau ressemble à ceci:
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
Vous avez besoin de 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);
À partir de PHP 5.5.0:
array_multisort(array_column($mylist, 'event_type'), SORT_DESC,
array_column($mylist, 'title'), SORT_ASC,
$mylist);
$mylist
est maintenant:
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',
),
)
Vous pouvez le faire avec usort
. L'argument $cmp_function
pourrait être:
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']);
}
Pour un nombre arbitraire de champs dans PHP 5.3, vous pouvez utiliser des fermetures pour créer une fonction de comparaison:
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')))
Pour un nombre arbitraire de champs de types différents dans 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')))
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);
J'ai essayé de code ci-dessous et j'ai réussi
code de tableau
$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')
);
fonction de tri de tableau d'appel
$songs = subval_sort($songs,'artist');
print_r($songs);
fonction de tri de tableau
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 fonction de tri inversé
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;
}
En améliorant le code de génie de @Stijn Leenknegt, voici ma fonction pragmatique à 2 centimes:
$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"]));
PHP7 Facilite le tri sur plusieurs colonnes à l'aide de l'opérateur de vaisseau spatial (<=>
), également appelé "opérateur de comparaison combiné" ou "opérateur de comparaison à trois voies".
Ressource: https://wiki.php.net/rfc/combined-comparison-operator
Le tri en plusieurs colonnes est aussi simple que d'écrire des tableaux équilibrés/relationnels des deux côtés de l'opérateur. Facile à faire!
Je n'ai pas utilisé uasort()
car je ne vois pas la nécessité de conserver les index d'origine.
Code: ( Démo )
$array = [
['ID' => 1, 'title' => 'Boring Meeting', 'date_start' => '2010-07-30', 'event_type' => 'meeting', 'state' => 'new-york'],
['ID' => 2, 'title' => 'Find My Stapler', 'date_start' => '2010-07-22', 'event_type' => 'meeting', 'state' => 'new-york'],
['ID' => 3, 'title' => 'Mario Party', 'date_start' => '2010-07-22', 'event_type' => 'party', 'state' => 'new-york'],
['ID' => 4, 'title' => 'Duct Tape Party', 'date_start' => '2010-07-28', 'event_type' => 'party', 'state' => 'california']
];
usort($array, function($a, $b) {
return [$a['state'], $a['event_type'], $a['date_start']] <=> [$b['state'], $b['event_type'], $b['date_start']];
});
var_export($array);
Sortie
array (
0 =>
array (
'ID' => 4,
'title' => 'Duct Tape Party',
'date_start' => '2010-07-28',
'event_type' => 'party',
'state' => 'california',
),
1 =>
array (
'ID' => 2,
'title' => 'Find My Stapler',
'date_start' => '2010-07-22',
'event_type' => 'meeting',
'state' => 'new-york',
),
2 =>
array (
'ID' => 1,
'title' => 'Boring Meeting',
'date_start' => '2010-07-30',
'event_type' => 'meeting',
'state' => 'new-york',
),
3 =>
array (
'ID' => 3,
'title' => 'Mario Party',
'date_start' => '2010-07-22',
'event_type' => 'party',
'state' => 'new-york',
),
)
si vous voulez trier un tableau multi-dimensionnel
le premier tableau est:
$results['total_quote_sales_person_wise']['quote_po'];
le second est:
$results['total_quote_sales_person_wise']['quote_count'];
ce tableau à la fois multidimensionnel que vous voulez trier en même temps, puis utilisez ce code:
array_multisort($results['total_quote_sales_person_wise']['quote_po'],SORT_DESC, $results['total_quote_sales_person_wise']['quote_count'],SORT_DESC);