2017-02-21 32 views
0

Так у меня есть 2D массив, который выглядит немного как это:Как сортировать по первичному ключу даты и вторичной буквенно-цифровой в PHP

[0] => Array(
    [date] => 23-01-2017 
    [name] => bbb 
    [othertext] => text2 
) 
[1] => Array(
    [date] => 23-01-2017 
    [name] => aaa 
    [othertext] => text3 
) 
[2] => Array(
    [date] => 24-01-2017 
    [name] => aaa 
    [othertext] => text1 
) 

Примечание: Этот вопрос не помечено как MySQL, используется база данных является MongoDB с типом сортировки 'date' => 'asc'.

В настоящее время это возвращается из моей базы данных, отсортированной по дате, но не учитывает свойство name. Я хотел бы сортировать это по date, а для записей с той же датой сортировать по name.

Мой текущий подход заключается в запуске array_multisort на данных:

array_multisort(
    $array['date'], SORT_STRING, 
    $array['name'], SORT_STRING, 
    $arrayCopy //<--This copy of the array has the full datetime object 
); 

Но затем сортирует дату в виде строки, поэтому в некоторых случаях он сортирует его неправильно; например 1st March будет идти до 2nd Feb. Если сначала помещать месяц, то снова сортируется неправильно, когда даты Dec/Jan сортируются.

Каков правильный подход к этому вопросу? Я видел упоминание о usort(), но я не уверен, как его реализовать в этом прецеденте. Имеются ли функции array_multisort для дат?

+0

Simp ly, добавьте этот вид в свой SQL-запрос 'ORDER BY date ASC, имя ASC' –

+0

http://stackoverflow.com/questions/2910611/php-sort-a-multidimensional-array-by-element-containing-date –

+0

@ Ayaou Этот вопрос не помечен как MySQL, он использует базу данных MongoDB - я расширил вопрос, чтобы указать это. :) – user3420034

ответ

1

В вашем запросе к базе данных:

SELECT * from `your_table_name` order by date asc, name asc; 

Может быть, это в MongoDB:

$cursor->sort(array('date' => 1, 'name' => 1)); 

См: http://php.net/manual/en/mongocursor.sort.php

Нет необходимости делать это в PHP после этого.

+0

Этот вопрос не помечен как MySQL, он использует базу данных MongoDB - я расширил вопрос до укажите это. :) – user3420034

+1

Обновлен мой ответ – Tschallacka

1

Я бы настоятельно предложил сделать это через базу данных.

Но если вы должны использовать usort или пытаются понять, как это работает:

$arr = [ 
    [ 
     'date' => '23-01-2017', 
     'name' => 'bbb', 
    ], 
    [ 
     'date' => '23-01-2017', 
     'name' => 'aaa', 
    ], 
    [ 
     'date' => '24-01-2017', 
     'name' => 'aaa', 
    ], 
]; 

function cmp($a, $b) 
{ 
    $aDate = DateTime::createFromFormat('d-m-Y', $a['date']); 
    $bDate = DateTime::createFromFormat('d-m-Y', $b['date']); 


    if ($aDate == $bDate) { 
     if ($a['name'] == $b['name']) { 
      return 0; 
     } 
     return ($a['name'] < $b['name']) ? -1 : 1; 
    } 
    return ($aDate < $bDate) ? -1 : 1; 
} 

usort($arr, "cmp"); 

print_r($arr); 

http://php.net/manual/en/function.usort.php

Выходы:

[0] => Array 
    (
     [date] => 23-01-2017 
     [name] => aaa 
    ) 

[1] => Array 
    (
     [date] => 23-01-2017 
     [name] => bbb 
    ) 

[2] => Array 
    (
     [date] => 24-01-2017 
     [name] => aaa 
    ) 
1

С usort-функции вы можете сделать:

$foo = array(
    0 => array(
    "date" => "23-01-2017", 
    "name" => "bbb", 
    "othertext" => "text2" 
), 
    1 => array(
    "date" => "23-01-2017", 
    "name" => "aaa", 
    "othertext" => "text3" 
), 
    2 => array(
    "date" => "24-01-2017", 
    "name" => "aaa", 
    "othertext" => "text1" 
) 
); 

usort($foo, function($a, $b) 
{ 
    return $a["date"] === $b["date"] ? strcmp($a["name"], $b["name"]) : strcmp(strtotime($a["date"]), strtotime($b["date"])); 
}); 

var_dump($foo);