PHP Ordena una matriz multidimensional por elemento que contiene fecha

113

Tengo una matriz como:

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
    )

)

¿Alguien puede sugerir una forma de ordenar esto en función del elemento de fecha y hora?

Tim
fuente

Respuestas:

206

Utilice usort()y una función de comparación personalizada:

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

EDITAR : Sus datos están organizados en una matriz de matrices. Para distinguirlos mejor, llamemos a los registros de matrices internas (datos), de modo que sus datos sean realmente una matriz de registros.

usortpasará dos de estos registros a la función de comparación dada date_compare()a la vez. date_compareluego extrae el "datetime"campo de cada registro como una marca de tiempo UNIX (un número entero), y devuelve la diferencia, de modo que el resultado será 0si ambas fechas son iguales, un número positivo si el primero ( $a) es mayor o un valor negativo si el el segundo argumento ( $b) es más grande. usort()utiliza esta información para ordenar la matriz.

Ferdinand Beyer
fuente
1
en este ejemplo, ¿$ array necesita contener los elementos $ ay $ b? - Recibo un error de función de comparación no válida
Tim
No, $ay $bmantendrá las matrices dentro $array. Asegúrese de no escribir mal el nombre de la función.
Ferdinand Beyer
no estoy seguro de entender. En mi ejemplo, tengo 3 matrices en la matriz - He confirmado el nombre, todavía obtengo una función de comparación no válida
Tim
Vea la explicación que agregué. ¡Probé el código y funciona bien para mí!
Ferdinand Beyer
9
No conozco CodeIgniter, pero ¿estás definiendo la función dentro de una clase? De lo que tiene que definirlo fuera de la clase o usar un argumento de devolución de llamada diferente:, usort($array, array($this, "date_compare"))para que usort()sepa que es una función / método de clase. Ver también: php.net/manual/en/…
Ferdinand Beyer
45

Esto debería funcionar. Convertí la fecha a hora Unix a través de strtotime.

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

La versión de una sola línea usaría múltiples métodos de matriz:

array_multisort(array_map('strtotime',array_column($originalArray,'datetime')),
                SORT_DESC, 
                $originalArray);
Dave Ninguno
fuente
Esto funciona muy bien. Simplemente reemplace: $ originalArray con el nombre de su matriz multidimensional. Y reemplace: 'fecha y hora' con el nombre de su campo de submatriz para la fecha. Gracias.
Estuve aquí
1
esta solución me está yendo bien. la opción de clasificación también es excelente (SORT_ASC o SORT_DESC). Muchas gracias.
Andras Barth
funciona muy bien con una pequeña advertencia (o eso, o estoy haciendo algo mal) ... el campo de fecha por el que necesito ordenar tiene fechas en el formato dd / mm / aaaa o aaaa / mm / dd (con barras). En ese caso, la clasificación no funcionó por alguna razón (clasificada solo por día, no por la fecha completa). Preprocesé las fechas para convertirlas en dd-mm-aaaa o aaaa-mm-dd y funcionó, ¡así que gracias! (¿Alguna idea sobre por qué funciona con guiones pero no barras?)
Javier Larroulet
array_multisort es el único método de clasificación que funcionó para clasificar mi archivo json por pubdate. Gracias.
grc
Funciona muy bien para mí, gracias
Fernando Torres
41

Desde php7 puedes usar el operador Spaceship :

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

http://us2.php.net/manual/en/function.array-multisort.php vea el tercer ejemplo:

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

?>

Para su información, usar un Unix (segundos desde 1970) o una marca de tiempo mysql (YmdHis - 20100526014500) sería más fácil para el analizador, pero creo que en su caso no hace ninguna diferencia.

Toby
fuente
5

Ordenar matriz de registros / assoc_arrays por campo de fecha y hora de mysql especificado y por orden:

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
fuente
Totalmente lo que necesito. Pero debe cambiar str_to_uppera 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
fuente
4

Simplemente puede resolver este problema usando usort () con la función de devolución de llamada. No es necesario escribir ninguna función personalizada.

$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
fuente
1

Me encontré con esta publicación, pero quería ordenar por tiempo al devolver los elementos dentro de mi clase y recibí un error.

Así que investigo el sitio web php.net y termino haciendo esto:

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

Puede encontrar ejemplos muy útiles en el sitio web PHP.net

Mi matriz se veía así:

  '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)
Ladrillo inmutable
fuente
1

Para 'd/m/Y'fechas:

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

    return $t1 > $t2;
});

donde $iesta el índice de la matriz

Borjovsky
fuente
1

Para aquellos que todavía buscan un resuelto de esta manera dentro de una clase con una función sortByDate, vea el código a continuación

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