PHP Ordina un array multidimensionale per elemento contenente la data


113

Ho un array come:

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
    )

)

Qualcuno può suggerire un modo per ordinare / ordinare questo in base all'elemento datetime?

Risposte:


206

Usa usort()e una funzione di confronto personalizzata:

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

EDIT : i tuoi dati sono organizzati in una matrice di array. Per distinguerli meglio, chiamiamo record di array interni (dati), in modo che i tuoi dati siano davvero un array di record.

usortpasserà due di questi record alla data funzione di confronto date_compare()alla volta. date_comparequindi estrae il "datetime"campo di ciascun record come un timestamp UNIX (un numero intero) e restituisce la differenza, in modo che il risultato sarà 0se entrambe le date sono uguali, un numero positivo se la prima ( $a) è maggiore o un valore negativo se la il secondo argomento ( $b) è più grande. usort()utilizza queste informazioni per ordinare l'array.


1
in questo esempio, $ array deve contenere gli elementi $ a e $ b? - Sto ricevendo un errore funzione di confronto non valida
Tim

No, $ae $bmanterrà gli array all'interno $array. Assicurati di non aver scritto male il nome della funzione.
Ferdinand Beyer

Non sono sicuro di capire. Nel mio esempio, ho 3 array nell'array - ho confermato il nome, ottenendo ancora una funzione di confronto non valida
Tim

Vedi la spiegazione che ho aggiunto. Ho testato il codice e per me funziona bene!
Ferdinand Beyer

9
Non conosco CodeIgniter, ma stai definendo la funzione all'interno di una classe? Quindi devi definirlo al di fuori della classe o usare un diverso argomento di callback:, in usort($array, array($this, "date_compare"))modo che usort()sappia che è una funzione / metodo di classe. Vedi anche: php.net/manual/en/…
Ferdinand Beyer

45

Questo dovrebbe funzionare. Ho convertito la data in unix time tramite strtotime.

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

La versione a una riga utilizzerebbe più metodi di array:

array_multisort(array_map('strtotime',array_column($originalArray,'datetime')),
                SORT_DESC, 
                $originalArray);

Funziona alla grande. Basta sostituire: $ originalArray con il nome del tuo array multidimensionale. E sostituisci: "datetime" con il nome del campo del sotto-array per la data. Grazie.
qui

1
questa soluzione sta andando bene per me. anche l'opzione di ordinamento è ottima (SORT_ASC o SORT_DESC). Molte grazie.
Andras Barth

funziona magnificamente con un piccolo avvertimento (o quello, o sto facendo qualcosa di sbagliato) ... il campo della data che devo ordinare ha date nel formato gg / mm / aaaa o aaaa / mm / gg (con barre). In tal caso, l'ordinamento non ha funzionato per qualche motivo (ordinato solo per giorno, non per l'intera data). Ho pre-elaborato le date per convertirle in gg-mm-aaaa o aaaa-mm-gg e ha funzionato quindi grazie !!! (qualche idea sul perché funziona con i trattini ma non con le barre?)
Javier Larroulet,

array_multisort è l'unico metodo di ordinamento che ha funzionato per ordinare il mio file json per pubdate. Grazie.
grc

Funziona davvero bene per me, grazie
Fernando Torres

41

Da php7 puoi usare l' operatore Spaceship :

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

6

http://us2.php.net/manual/en/function.array-multisort.php vedi terzo esempio:

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

?>

Cordiali saluti, utilizzare un unix (secondi dal 1970) o un timestamp mysql (YmdHis - 20100526014500) sarebbe più facile per il parser ma penso che nel tuo caso non faccia differenza.


5

Ordinamento dell'array di record / assoc_arrays per campo datetime mysql specificato e per ordine:

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

Totalmente quello di cui ho bisogno. Ma deve cambiare str_to_upperin 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);

4

Puoi semplicemente risolvere questo problema usando usort () con la funzione di callback. Non è necessario scrivere alcuna funzione personalizzata.

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

1

Mi sono imbattuto in questo post ma volevo ordinare in base all'ora quando ho restituito gli elementi all'interno della mia classe e ho ricevuto un errore.

Quindi cerco il sito web php.net e finisco per fare questo:

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

Puoi trovare esempi molto utili nel sito web PHP.net

Il mio array aveva questo aspetto:

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

1

Per le 'd/m/Y'date:

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

    return $t1 > $t2;
});

dov'è $il'indice dell'array


1

Per coloro che stanno ancora cercando di risolverlo in questo modo all'interno di una classe con una funzione sortByDate, vedere il codice seguente

<?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;

    }
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.