web-dev-qa-db-fra.com

PHP trier le tableau par deux valeurs de champ

J'ai un tableau comme ça 

 Array (
 [0] => Array ("destination" => "Sydney", 
 "Airlines" => "airline_1", 
 "One_way_fare" => 100, 
 " return_fare => 300 
), 
 [2] => Array ("destination" => "Sydney", 
 "airlines" => "airline_2", 
 "one_way_fare" => 150, 
 "return_fare => 350 
), 
 [3] => Array (" destination "=>" Sydney ", 
" airlines "=>" airline_3 ", 
" one_way_fare " => 180, 
 "Return_fare => 380 
) 
) 

Comment puis-je trier la valeur par return_fare asc, one_way_fare asc?

J'ai essayé array_multisort () mais j'ai fini par avoir des données mélangées ..

asort ne fonctionne que pour un tableau à une dimension, je dois trier par deux valeurs ou plus, comment puis-je obtenir cela comme en SQL, ordre par champ1 asc, champ2 asc?

55
flyclassic

array_multisort() est la fonction correcte, vous devez vous être trompé:

// Obtain a list of columns
foreach ($data as $key => $row) {
    $return_fare[$key]  = $row['return_fare'];
    $one_way_fare[$key] = $row['one_way_fare'];
}

// Sort the data with volume descending, edition ascending
array_multisort($return_fare, SORT_ASC, $one_way_fare, SORT_ASC, $data);

Si vous consultez les commentaires sur la page de manuel de PHP pour array_multisort(), vous pouvez trouver une fonction très utile array_orderby() qui vous permet de réduire ce qui précède à ceci:

$sorted = array_orderby($data, 'return_fare', SORT_ASC, 'one_way_fare', SORT_ASC);

Pour éviter les boucles, utilisez array_column() (à partir de PHP 5.5.0):

array_multisort(array_column($data, 'return_fare'),  SORT_ASC,
                array_column($data, 'one_way_fare'), SORT_ASC,
                $data);
87
Tatu Ulmanen

En plus de array_multisort(), qui nécessite de créer d’abord des tableaux de colonnes, il existe également usort() qui n’exige pas une telle chose.

usort($data, function($a, $b) { 
    $rdiff = $a['return_fare'] - $b['return_fare'];
    if ($rdiff) return $rdiff; 
    return $a['one_way_fare'] - $b['one_way_fare']; 
}); // anonymous function requires PHP 5.3 - use "normal" function earlier
31
etarion

Ou vous pouvez utiliser uasort comme suit

uasort($arr, function($a,$b){
    $c = $a['return_fare'] - $b['return_fare'];
    $c .= $a['one_way_fare'] - $b['one_way_fare'];
    return $c;
});

Fiddle

9

Un autre exemple utilisant l'opérateur de vaisseau spatial.

usort($data, function($a, $b) { 
    return $a['return_fare'] <=> $b['return_fare'] ?: $a['one_way_fare'] <=> $b['one_way_fare'] 
});
5
user634545

Ohh, j'ai réussi à résoudre ma propre question à nouveau ....

function array_multi_sort($array, $on1,$on2, $order=SORT_ASC) 
{

    foreach($array as $key=>$value){
        $one_way_fares[$key] = $value[$on2];
        $return_fares[$key] = $value[$on1];
    }

    array_multisort($return_fares,$order,$one_way_fares,$order,$array);
}

Le problème, c’est que j’ai manqué le dernier paramètre $ array sur array_multisort($return_fares,$order,$one_way_fares,$order,$array);

plus tôt!

0
flyclassic

Je vais répondre à cela d'une manière qui peut être généralisée, peu importe le nombre d'éléments que vous souhaitez trier!

Tri sur return_fare puis one_way_fare:

usort($data, function($a, $b) {
   if ($a['return_fare'] != $b['return_fare']) {
      return $a['return_fare'] <=> $b['return_fare'];
   }

   return $a['one_way_fare'] <=> $b['one_way_fare'];
});

Tri sur return_fare, puis one_way_fare, puis destination:

usort($data, function($a, $b) {
   if ($a['return_fare'] != $b['return_fare']) {
      return $a['return_fare'] <=> $b['return_fare'];
   }

   if ($a['one_way_fare'] != $b['one_way_fare']) {
      return $a['one_way_fare'] <=> $b['one_way_fare'];
   }

   return strnatcasecmp($a['destination'], $b['destination']);
});

Tri sur seulement return_fare:

usort($data, function($a, $b) {
   return $a['return_fare'] <=> $b['return_fare'];
});

Remarque: vous ne devez pas utiliser une fonction anonyme avec usort!

function cmp($a, $b) {
   return $a['return_fare'] <=> $b['return_fare'];
}

usort($data, 'cmp');


// Use a function inside a class:
class MyClass {
   public static function compare($a, $b) {
      return $a['return_fare'] <=> $b['return_fare'];
   }
}

usort($data, ['MyClass', 'compare']);

Vous pouvez également les chaîner en utilisant l'opérateur Elvis (?:):

usort($data, function($a, $b) {
      return $a['return_fare'] <=> $b['return_fare'] ?:
             $a['one_way_fare'] <=> $b['one_way_fare'] ?:
             strnatcasecmp($a['destination'], $b['destination']);
});

Ce dernier exemple utilisait l'opérateur de vaisseau spatial (<=>) et l'opérateur Elvis (?:). La programmation n'est-elle pas géniale?

0
Westy92