PHP Trier un tableau multidimensionnel par élément contenant la date

114

J'ai un tableau tel que:

Array
(
[0] => Array
    (
        [id] => 2
        [type] => comment
        [text] => hey
        [datetime] => 2010-05-15 11:29:45
    )

[1] => Array
    (
        [id] => 3
        [type] => status
        [text] => oi
        [datetime] => 2010-05-26 15:59:53
    )

[2] => Array
    (
        [id] => 4
        [type] => status
        [text] => yeww
        [datetime] => 2010-05-26 16:04:24
    )

)

Quelqu'un peut-il suggérer un moyen de trier / ordonner cela en fonction de l'élément datetime?

Tim
la source

Réponses:

206

Utilisez usort()et une fonction de comparaison personnalisée:

function date_compare($a, $b)
{
    $t1 = strtotime($a['datetime']);
    $t2 = strtotime($b['datetime']);
    return $t1 - $t2;
}    
usort($array, 'date_compare');

EDIT : Vos données sont organisées dans un tableau de tableaux. Pour mieux les distinguer, appelons les enregistrements de tableaux internes (données), afin que vos données soient vraiment un tableau d'enregistrements.

usorttransmettra deux de ces enregistrements à la fonction de comparaison donnée date_compare()à un moment donné. date_comparepuis extrait le "datetime"champ de chaque enregistrement sous la forme d'un horodatage UNIX (un entier), et renvoie la différence, de sorte que le résultat sera 0si les deux dates sont égales, un nombre positif si le premier ($a ) est plus grand ou une valeur négative si le le deuxième argument ( $b) est plus grand. usort()utilise ces informations pour trier le tableau.

Ferdinand Beyer
la source
1
dans cet exemple, est-ce que $ array doit contenir les éléments $ a et $ b? - Je reçois une erreur de fonction de comparaison invalide
Tim
Non, $aet $bcontiendra les tableaux à l'intérieur $array. Assurez-vous que vous n'avez pas mal orthographié le nom de la fonction.
Ferdinand Beyer
Je ne suis pas sûr de comprendre. Dans mon exemple, j'ai 3 tableaux dans le tableau - j'ai confirmé le nom, j'obtiens toujours une fonction de comparaison invalide
Tim
Voir l'explication que j'ai ajoutée. J'ai testé le code et cela fonctionne très bien pour moi!
Ferdinand Beyer
9
Je ne connais pas CodeIgniter, mais définissez-vous la fonction à l'intérieur d'une classe? Ensuite, vous devez soit le définir en dehors de la classe, soit utiliser un argument de rappel différent:, usort($array, array($this, "date_compare"))pour que vous usort()sachiez que c'est une fonction / méthode de classe. Voir aussi: php.net/manual/en
Ferdinand Beyer
46

Cela devrait fonctionner. J'ai converti la date en heure Unix via strtotime.

  foreach ($originalArray as $key => $part) {
       $sort[$key] = strtotime($part['datetime']);
  }
  array_multisort($sort, SORT_DESC, $originalArray);

La version à une ligne utiliserait plusieurs méthodes de tableau:

array_multisort(array_map('strtotime',array_column($originalArray,'datetime')),
                SORT_DESC, 
                $originalArray);
Dave Aucun
la source
Cela fonctionne très bien. Remplacez simplement: $ originalArray par le nom de votre tableau multidimensionnel. Et remplacez: 'datetime' par le nom de votre champ de sous-tableau pour la date. Merci.
washere
1
cette solution me convient bien. l'option de tri est également excellente (SORT_ASC ou SORT_DESC). Merci beaucoup.
Andras Barth
fonctionne à merveille avec une petite mise en garde (soit ça, soit je fais quelque chose de mal) ... le champ de date dont je dois trier a des dates au format jj / mm / aaaa ou aaaa / mm / jj (avec des barres obliques). Dans ce cas, le tri n'a pas fonctionné pour une raison quelconque (trié uniquement par jour, pas par date entière). J'ai prétraité les dates pour les convertir en jj-mm-aaaa ou aaaa-mm-jj et cela a fonctionné alors merci !!! (des idées sur pourquoi cela fonctionne avec des tirets mais pas des barres obliques?)
Javier Larroulet
array_multisort est la seule méthode de tri qui a fonctionné pour trier mon fichier json par pubdate. Merci.
grc
Travaille vraiment bien pour moi, merci
Fernando Torres
41

Depuis php7, vous pouvez utiliser l' opérateur Spaceship :

usort($array, function($a, $b) {
  return new DateTime($a['datetime']) <=> new DateTime($b['datetime']);
});
Federkun
la source
6

http://us2.php.net/manual/en/function.array-multisort.php voir le troisième exemple:

<?php

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

foreach ($data as $key => $row) {
    $volume[$key]  = $row['volume'];
    $edition[$key] = $row['edition'];
}

array_multisort($volume, SORT_DESC, $edition, SORT_ASC, $data);

?>

Pour info, utiliser un horodatage unix (secondes à partir de 1970) ou mysql (YmdHis - 20100526014500) serait plus facile pour l'analyseur, mais je pense que dans votre cas, cela ne fait aucune différence.

Toby
la source
5

Tri du tableau d'enregistrements / assoc_arrays par champ datetime mysql spécifié et par ordre:

function build_sorter($key, $dir='ASC') {
    return function ($a, $b) use ($key, $dir) {
        $t1 = strtotime(is_array($a) ? $a[$key] : $a->$key);
        $t2 = strtotime(is_array($b) ? $b[$key] : $b->$key);
        if ($t1 == $t2) return 0;
        return (strtoupper($dir) == 'ASC' ? ($t1 < $t2) : ($t1 > $t2)) ? -1 : 1;
    };
}


// $sort - key or property name 
// $dir - ASC/DESC sort order or empty
usort($arr, build_sorter($sort, $dir));
falko
la source
Totalement ce dont j'ai besoin. Mais doit changer str_to_upperpour strtoupper.
Jimmy Adaro
4

$array = Array
(
  [0] => Array
   (
    [id] => 2
    [type] => comment
    [text] => hey
    [datetime] => 2010-05-15 11:29:45
   )

 [1] => Array
  (
    [id] => 3
    [type] => status
    [text] => oi
    [datetime] => 2010-05-26 15:59:53
  )

  [2] => Array
   (
    [id] => 4
    [type] => status
    [text] => yeww
    [datetime] => 2010-05-26 16:04:24
   )

   );
   print_r($array);   
   $name = 'datetime';
   usort($array, function ($a, $b) use(&$name){
      return $a[$name] - $b[$name];});

   print_r($array);
Ajit Kumar
la source
4

Vous pouvez simplement résoudre ce problème en utilisant usort () avec la fonction de rappel. Pas besoin d'écrire une fonction personnalisée.

$your_date_field_name = 'datetime';
usort($your_given_array_name, function ($a, $b) use (&$your_date_field_name) {
    return strtotime($a[$your_date_field_name]) - strtotime($b[$your_date_field_name]);
});
Faisal
la source
1

Je suis tombé sur ce post mais je voulais trier par heure lors du retour des articles dans ma classe et j'ai eu une erreur.

Je recherche donc le site Web php.net et finis par faire ceci:

class MyClass {
   public function getItems(){
      usort( $this->items, array("MyClass", "sortByTime") );
      return $this->items;
   }
   public function sortByTime($a, $b){
      return $b["time"] - $a["time"];
   }
}

Vous pouvez trouver des exemples très utiles sur le site PHP.net

Mon tableau ressemblait à ceci:

  'recent' => 
    array
      92 => 
        array
          'id' => string '92' (length=2)
          'quantity' => string '1' (length=1)
          'time' => string '1396514041' (length=10)
      52 => 
        array
          'id' => string '52' (length=2)
          'quantity' => string '8' (length=1)
          'time' => string '1396514838' (length=10)
      22 => 
        array
          'id' => string '22' (length=2)
          'quantity' => string '1' (length=1)
          'time' => string '1396514871' (length=10)
      81 => 
        array
          'id' => string '81' (length=2)
          'quantity' => string '2' (length=1)
          'time' => string '1396514988' (length=10)
Brique immuable
la source
1

Pour les 'd/m/Y'dates:

usort($array, function ($a, $b, $i = 'datetime') { 
    $t1 = strtotime(str_replace('/', '-', $a[$i]));
    $t2 = strtotime(str_replace('/', '-', $b[$i]));

    return $t1 > $t2;
});

$iest l'index du tableau

Borjovsky
la source
1

Pour ceux qui cherchent encore à résoudre le problème de cette façon dans une classe avec une fonction sortByDate, voir le code ci-dessous

<?php

class ContactsController 
{
    public function __construct()
    {
    //
    }


    function sortByDate($key)
    {
        return function ($a, $b) use ($key) {
            $t1 = strtotime($a[$key]);
            $t2 = strtotime($b[$key]);
            return $t2-$t1;
        };

    }

    public function index()
    {

        $data[] = array('contact' => '434343434', 'name' => 'dickson','updated_at' =>'2020-06-11 12:38:23','created_at' =>'2020-06-11 12:38:23');
        $data[] = array('contact' => '434343434', 'name' => 'dickson','updated_at' =>'2020-06-16 12:38:23','created_at' =>'2020-06-10 12:38:23');
        $data[] = array('contact' => '434343434', 'name' => 'dickson','updated_at' =>'2020-06-7 12:38:23','created_at' =>'2020-06-9 12:38:23');


        usort($data, $this->sortByDate('updated_at'));

        //usort($data, $this->sortByDate('created_at'));
        echo $data;

    }
}
Dickson Godwin
la source