323 votes

Comment trier les tableaux et les données en PHP ?

Cette question est destinée à servir de référence pour les questions relatives au tri des tableaux en PHP. Il est facile de penser que votre cas particulier est unique et mérite une nouvelle question, mais la plupart sont en fait des variations mineures de l'une des solutions de cette page.

Si votre question est fermée parce qu'elle fait double emploi avec celle-ci, demandez à ce qu'elle soit rouverte uniquement si vous pouvez expliquer pourquoi elle diffère sensiblement de toutes les questions ci-dessous.

Comment trier un tableau en PHP ?
Comment trier un complexe tableau en PHP ?
Comment trier un tableau d'objets en PHP ?


  1. Tableaux unidimensionnels de base ; y compris les tableaux multidimensionnels, y compris les tableaux d'objets ; y compris le tri d'un tableau en fonction d'un autre.

  2. Triage avec SPL

  3. Tri stable

Pour la réponse pratique utilisant les fonctions existantes de PHP, voir 1., pour la réponse académique détaillée sur les algorithmes de tri (que les fonctions de PHP implémentent et que vous ), voir 2. mai nécessaire pour les cas vraiment, vraiment complexes), voir 2.

0 votes

@jterry Exactement, c'est pour cela que je l'ai fait, pour avoir enfin une bonne question de référence pour conclure. Répondre à chaque flocon de neige individuellement n'aide personne :)

3 votes

Je pense que les gens devraient simplement jeter un coup d'oeil à php.net.

0 votes

@Alex Ha ! Absolument. Le problème est que personne ne fait de RTFM. :D

3voto

Smartik Points 614

Tri multidimensionnel par valeur de clé

Tri naturel d'un tableau multidimensionnel en fonction d'une valeur clé et en conservant l'ordre original (sans mélanger les clés principales) :

function multisortByKeyValue( $k, $arr ) {
    $ids   = array();
    $index = 1;

    foreach ( $arr as $key => $row ) {
        $ids[ $key ] = intval( $row[ $k ] ) . '-' . $index . '-' . $key;
        $index ++;
    }

    natsort( $ids );

    $arr = array_merge( $ids, $arr );

    return $arr;
}

Cas de test :

$arr = array(
    'id1' => array(
        'label'    => 'ID 1',
        'priority' => 30,
    ),
    'id2' => array(
        'label'    => 'ID 2',
        'priority' => 70,
    ),
    'id3' => array(
        'label'    => 'ID 3',
        'priority' => 20,
    ),
    'id4' => array(
        'label'    => 'ID 4',
        'priority' => 30,
    ),
);

$sorted = multisortByKeyValue( 'priority', $arr );

// $sorted equals to:
/*
array (
  'id3' => array (
    'label' => 'ID 3',
    'priority' => 20,
  ),
  'id1' => array (
    'label' => 'ID 1',
    'priority' => 30,
  ),
  'id4' => array (
    'label' => 'ID 4',
    'priority' => 30,
  ),
  'id2' => array (
    'label' => 'ID 2',
    'priority' => 70,
  ),
)
*/

3voto

mickmackusa Points 18931

Cette page est très complète, mais je veux ajouter un peu plus sur l'utilité impressionnante de l'opérateur spaceship (opérateur de comparaison à trois voies) -- un bel enfant de PHP7+.

Utilisation de l'opérateur vaisseau spatial pour mettre en œuvre des conditions de tri multiples

Cela permet de réduire considérablement le gonflement du code et d'en améliorer la lisibilité.

Lors de l'écriture de votre tri personnalisé ( usort() / uasort() / uksort() ) pour traiter des conditions multiples, il vous suffit d'écrire des tableaux équilibrés de part et d'autre de l'opérateur et de renvoyer le résultat. Plus de blocs de conditions imbriqués ou de retours multiples.

Les éléments des deux côtés de l'opérateur seront parcourus de gauche à droite, un par un, et l'évaluation sera renvoyée dès qu'un élément non lié sera rencontré ou lorsque tous les éléments auront été comparés.

Des échantillons de données pour mes démonstrations :

$multidimArray = [
    'a' => [
        'boolean' => true,
        'natString' => 'text10',
        'object' => (object)['prop' => 2],
        'float' => -.5,
        'mixed' => []
    ],
    'b' => [
        'boolean' => true,
        'natString' => 'text12',
        'object' => (object)['prop' => 4],
        'float' => 0,
        'mixed' => null
    ],
    'c' => [
        'boolean' => false,
        'natString' => 'text100',
        'object' => (object)['prop' => 9],
        'float' => -.5,
        'mixed' => false
    ],
    'd' => [
        'boolean' => true,
        'natString' => 'text1',
        'object' => (object)['prop' => 9],
        'float' => -5,
        'mixed' => "\0"
    ],
    'e' => [
        'boolean' => false,
        'natString' => 'text2',
        'object' => (object)['prop' => 2],
        'float' => .5,
        'mixed' => ''
    ]
];

Démonstrations (pour éviter le gonflement des pages de Stackoverflow, veuillez voir le lien vers la démo pour les sorties) :

  • Logique de tri :

    1. booléen DESC (false = 0, true = 1, donc les vrais avant les faux)
    2. float ASC

      uasort($multidimArray, function($a, $b) {
          return [$b['boolean'], $a['float']] <=> [$a['boolean'], $b['float']];
      });
  • Logique de tri :

    1. mixte ASC
    2. objet ASC
    3. booléen ASC

      uasort($multidimArray, function($a, $b) {
          return [$a['mixed'], $a['object']->prop, $a['boolean']] <=> [$b['mixed'], $b['object']->prop, $b['boolean']];
      });
  • Logique de tri :

    1. nombre de propriétés de l'objet ASC
    2. itérabilité du DESC mixte
    3. natString longueur ASC
    4. natString ASC

      uasort($multidimArray, function($a, $b) {
          return [count(get_object_vars($a['object'])), is_iterable($a['mixed']), strlen($a['natString']), $a['natString']]
                 <=>
                 [count(get_object_vars($b['object'])), is_iterable($b['mixed']), strlen($b['natString']), $b['natString']];
      });

Cette syntaxe vous permet de trier les valeurs, les résultats fonctionnels, les données imbriquées et la direction du tri de manière élégante. Cela vaut vraiment la peine de la mettre dans votre ceinture d'outils php ... pour les cas où vous traitez des données ne provenant pas d'une base de données - parce que, bien sûr, SQL serait une technique beaucoup plus raisonnable.

À votre discrétion, à partir de PHP7.4, vous pouvez utiliser la syntaxe des flèches avec ces fonctions anonymes. Même script avec la syntaxe de la flèche .

2voto

Ihor Burlachenko Points 2037

Il est très pratique de trier des tableaux avec trié de la fonction Nspl :

Triage de base

// Sort array
$sorted = sorted([3, 1, 2]);

// Sort array in descending order
$sortedDesc = sorted([3, 1, 2], true);

Triage par résultat de fonction

// Sort array by the result of a given function (order words by length)
$sortedByLength = sorted(['bc', 'a', 'abc'], 'strlen');
$sortedByLengthDesc = sorted(['bc', 'a', 'abc'], true, 'strlen');

// Sort array by the result of user-defined function (order words by the 1st character)
$sortedByTheFirstCharacter = sorted(['bc', 'a', 'abc'], function($v) { return $v[0]; }); 

// Which is the same as
$sortedByTheFirstCharacter = sorted(['bc', 'a', 'abc'], itemGetter(0));
$sortedByTheFirstCharacterDesc = sorted(['bc', 'a', 'abc'], true, itemGetter(0));

// itemGetter(0) returns a function which takes an argument with access by index/key
// and returns the value at index 0

Tri d'un tableau multidimensionnel

// Sort multidimensional array (sort list of users by their names)
$users = [
    array('name' => 'Robert', 'age' => 20),
    array('name' => 'Alex', 'age' => 30),
    array('name' => 'Jack', 'age' => 25),
];
$sortedByName = sorted($users, itemGetter('name'));
$sortedByNameDesc = sorted($users, true, itemGetter('name'));

// itemGetter('name') returns a function which takes an argument with access by index/key
// and returns the value of the 'name' key

Tri d'un tableau d'objets

// Lets assume we have class User(name, age) with properties name and age
// and public methods getName() and getAge()
$users = [
    new User('Robert', 20),
    new User('Alex', 30),
    new User('Jack', 25),
];

// Sort list of objects by property value (sort list of users by their name)
$sortedByName = sorted($users, propertyGetter('name'));
$sortedByNameDesc = sorted($users, true, propertyGetter('name'));

// propertyGetter('name') returns a function which takes an object
// and returns the value of its 'name' property

// Sort list of objects by method result (sort list of users by their age)
$sortedByAge = sorted($users, methodCaller('getAge'));
$sortedByAgeDesc = sorted($users, true, methodCaller('getAge'));

// methodCaller('getAge') returns a function which takes an object
// and returns the result of its getAge() method

Triage avec une fonction de comparaison

// Sort with a comparison function (order words lexicographically with strcmp)
$sortedLexicographically = sorted(['bc', 'a', 'abc'], false, null, 'strcmp');

// Sort with user-defined comparison function (order words by the 1st character)
$sortedByTheFirstCharacter = sorted(['bc', 'a', 'abc'], false, null, function($v1, $v2) {
    return chr($v1[0]) - chr($v2[0]);
});

Vous pouvez voir tous ces exemples aquí .

2voto

GAV Points 29

Si vous voulez commander par la valeur de la clé, vous pouvez le faire sur une seule ligne, élégante et claire. Ceci ordonne par le prix en ordre croissant. Utilise array_multisort et array_column.

   Array([0] => Array ( [name] => eggs [price] => 1 ) [1] => Array ( [name] => coffee [price] => 9.99 ) [2] => Array ( [name] => rice [price] => 4.04 ) )

   array_multisort (array_column($array, 'price'), SORT_ASC, $array);

pour produire

     Array ( [0] => Array ( [name] => eggs [price] => 1 ) [1] => Array ( [name] => rice [price] => 4.04 ) [2] => Array ( [name] => coffee [price] => 9.99 ) )

0voto

Lucas Bustamante Points 3318

Si vous souhaitez trier un tableau en fonction de la valeur absolue la plus élevée sur la base de plusieurs critères, voici un moyen simple de le faire :

usort($arr, function($item, $nextItem) {
    return (max($nextItem->firstNumber, $nextItem->secondNumber)) - (max($item->firstNumber, $item->secondNumber));
});

Exemple :

$foo = new stdClass;
$foo->createdDate = '10';
$foo->uploadedDate = '5';

$bar = new stdClass;
$bar->createdDate = '1';
$bar->uploadedDate = '12';

$baz = new stdClass;
$baz->createdDate = '25';
$baz->uploadedDate = '0';

$arr = [$foo, $bar, $baz];

// Order array by the highest number between "createdDate" and "uploadedDate".
usort($arr, function($item, $nextItem) {
    return (max($nextItem->createdDate, $nextItem->uploadedDate)) - (max($item->createdDate, $item->uploadedDate));
});

Résultats dans :

array (
  0 => 
  (object) array(
     'createdDate' => '25',
     'uploadedDate' => '0',
  ),
  1 => 
  (object) array(
     'createdDate' => '1',
     'uploadedDate' => '12',
  ),
  2 => 
  (object) array(
     'createdDate' => '10',
     'uploadedDate' => '5',
  ),
)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X