PHP Çok boyutlu bir diziyi tarih içeren öğeye göre sıralar


114

Şöyle bir dizim var:

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
    )

)

Herhangi biri bunu datetime öğesine göre sıralamak / düzenlemek için bir yol önerebilir mi?

Yanıtlar:


206

usort()Özel bir karşılaştırma işlevi kullanın :

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

DÜZENLEME : Verileriniz bir dizi dizide düzenlenir. Bunları daha iyi ayırt etmek için, iç diziler (veri) kayıtlarını çağıralım, böylece verileriniz gerçekten bir kayıt dizisi olsun.

usortbu kayıtlardan ikisini bir seferde verilen karşılaştırma işlevine date_compare()geçirir. date_comparedaha sonra "datetime", her kaydın alanını UNIX zaman damgası (bir tamsayı) olarak çıkarır ve farkı döndürür, böylece sonuç, 0her iki tarih de eşitse, birincisi ( $a) büyükse pozitif bir sayı veya eğer ikinci bağımsız değişken ( $b) daha büyüktür. usort()diziyi sıralamak için bu bilgiyi kullanır.


1
bu örnekte, $ dizinin $ a ve $ b öğelerini içermesi gerekir mi? - geçersiz karşılaştırma işlevi hatası alıyorum
Tim

Hayır $ave $bdizileri içeride tutacak $array. İşlev adını yanlış yazmadığınızdan emin olun.
Ferdinand Beyer

anladığımdan emin değilim. Örneğimde, dizide 3 dizim var - adı doğruladım, hala geçersiz karşılaştırma işlevi alıyorum
Tim,

Eklediğim açıklamaya bakın. Kodu test ettim ve benim için iyi çalışıyor!
Ferdinand Beyer

9
CodeIgniter'ı bilmiyorum ama işlevi bir sınıf içinde mi tanımlıyorsunuz? Ya onu sınıfın dışında tanımlamanız ya da farklı bir geri çağırma argümanı kullanmanız gerekir:, usort($array, array($this, "date_compare"))böylece bunun usort()bir sınıf işlevi / yöntemi olduğunu bilir. Ayrıca bakınız: php.net/manual/en/…
Ferdinand Beyer

46

Bu çalışmalı. Tarihi strtotime aracılığıyla unix zamanına çevirdim.

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

Tek satırlık sürüm, birden çok dizi yöntemi kullanır:

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

Bu harika çalışıyor. $ OriginalArray'i çok boyutlu dizinizin adıyla değiştirin. Ve: 'tarihsaat'i tarih için alt dizi alanınızın adıyla değiştirin. Teşekkürler.
washere

1
bu çözüm benim için iyi gidiyor. sıralama seçeneği de harika (SORT_ASC veya SORT_DESC). Çok teşekkürler.
Andras Barth

küçük bir uyarı ile güzel bir şekilde çalışıyor (ya öyle ya da yanlış bir şey yapıyorum) ... Sıralamam gereken tarih alanı gg / aa / yyyy veya yyyy / aa / gg (eğik çizgilerle) biçiminde tarihlere sahip. Bu durumda, sıralama herhangi bir nedenle işe yaramadı (tüm tarihe değil, yalnızca güne göre sıralandı). Tarihleri ​​gg-aa-yyyy veya yyyy-aa-gg'ye dönüştürmek için önceden işledim ve işe yaradı çok teşekkürler !!! (neden kısa çizgilerle çalışıp eğik çizgilerle
çalışmadığına dair bir fikriniz var

array_multisort, json dosyamı yayın tarihine göre sıralamak için çalışan tek sıralama yöntemidir. Teşekkürler.
grc

Benim için gerçekten iyi çalışıyor, teşekkürler
Fernando Torres


6

http://us2.php.net/manual/en/function.array-multisort.php üçüncü örneğe bakın:

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

?>

fyi, bir unix (1970'den saniyeler) veya mysql zaman damgası (YmdHis - 20100526014500) kullanmak ayrıştırıcı için daha kolay olurdu, ancak sizin durumunuzda hiçbir fark yaratmadığını düşünüyorum.


5

Kayıtların / assoc_arrays dizisinin belirtilen mysql datetime alanına ve sıraya göre sıralanması:

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

Tamamen ihtiyacım olan şey. Ama değiştirmelisiniz str_to_upperiçin 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

Geri arama fonksiyonu ile usort () kullanarak bu sorunu çözebilirsiniz . Herhangi bir özel fonksiyon yazmaya gerek yok.

$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

Bu yazıya rastladım ancak sınıfımdaki eşyaları iade ederken zamana göre sıralamak istedim ve bir hata aldım.

Bu yüzden php.net web sitesini araştırıyorum ve sonunda şunu yapıyorum:

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

PHP.net web sitesinde çok faydalı örnekler bulabilirsiniz

Dizim şuna benziyordu:

  '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

İçin 'd/m/Y'tarihleri:

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

    return $t1 > $t2;
});

$idizi indeksi nerede


1

Hala sortByDate işlevine sahip bir sınıf içinde sorunu bu şekilde çözmüş arayanlar için aşağıdaki koda bakı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;

    }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.