Reputation: 284
So I'm not exactly sure if the title fits it best, but here's what the array looks like:
array (
[0] => array (
[category] => 'Value_1'
[date] => '01/01/2011'
[data] => 'A'
)
[1] => array (
[category] => 'Value_3'
[date] => '01/01/2000'
[data] => 'B'
)
[2] => array (
[category] => 'Value_2'
[date] => '01/01/2011'
[data] => 'D'
)
[3] => array (
[category] => 'Value_2'
[date] => '01/01/2010'
[data] => 'A'
)
[4] => array (
[category] => 'Value_2'
[date] => '01/01/2011'
[data] => 'C'
)
)
How I'd like this data to be sorted would be the following:
The example array would then be sorted to array ([0], [1], [4], [2], [3])
, more specifically:
array (
[0] => array (
[category] => 'Value_1'
[date] => '01/01/2011'
[data] => 'A'
)
[1] => array (
[category] => 'Value_3'
[date] => '01/01/2000'
[data] => 'B'
)
[2] => array (
[category] => 'Value_2'
[date] => '01/01/2011'
[data] => 'C'
)
[3] => array (
[category] => 'Value_2'
[date] => '01/01/2011'
[data] => 'D'
)
[4] => array (
[category] => 'Value_2'
[date] => '01/01/2010'
[data] => 'A'
)
)
My issue is I know I'll need usort
and/or array_multisort()
, but I'm not sure exactly sure how to efficiently iterate through a loop in order to sort with the criteria I gave.
Upvotes: 2
Views: 1540
Reputation: 4399
Supposing your array in $data
variable, try this:
$data = Array(
0 => array(
"category" => 'Value_1',
"date" => '01/01/2011',
"data" => 'A'
),
1 => array(
"category" => 'Value_3',
"date" => '01/01/2000',
"data" => 'B'
),
2 => array(
"category" => 'Value_2',
"date" => '01/01/2011',
"data" => 'D'
),
3 => array(
"category" => 'Value_2',
"date" => '01/01/2010',
"data" => 'A'
),
4 => array(
"category" => 'Value_2',
"date" => '01/01/2011',
"data" => 'C'
)
);
$sorted = false;
foreach ($data as $index => $row) {
$data[$index]['date'] = strtotime($data[$index]['date']);
}
while (!$sorted) {
$aux = null;
$prevCat = null;
$prevDate = null;
$prevData = null;
foreach ($data as $index => $row) {
if ($prevCat != $row['category']) {
$prevCat = $row['category'];
$prevDate = $row['date'];
$prevData = $row['data'];
continue;
} else {
if ($row['date'] > $prevDate) {
$sorted = false;
$aux = $data[$index - 1];
$data[$index - 1] = $row;
$data[$index] = $aux;
break;
}
if ($row['date'] == $prevDate && $row['data'] < $prevData) {
$sorted = false;
$aux = $data[$index - 1];
$data[$index - 1] = $row;
$data[$index] = $aux;
break;
}
$prevCat = $row['category'];
$prevDate = $row['date'];
$prevData = $row['data'];
}
}
$sorted = ($aux == null);
}
foreach ($data as $index => $row)
$data[$index]['date'] = date("m/d/Y", $data[$index]['date']);
var_dump($data);
// outputs
array(5) {
[0] => array(3) {
["category"] => string(7) "Value_1"
["date"] => string(10) "01/01/2011
["data"] => string(1) "A"
}
[1] => array(3) {
["category"] => string(7) "Value_3"
["date"] => string(10) "01/01/2000"
["data"] => string(1) "B"
}
[2] => array(3) {
["category"] => string(7) "Value_2"
["date"] => string(10) "01/01/2011"
["data"] => string(1) "C"
}
[3] => array(3) {
["category"] => string(7) "Value_2"
["date"] => string(10) "01/01/2011"
["data"] => string(1) "D"
}
[4] => array(3) {
["category"] => string(7) "Value_2"
["date"] => string(10) "01/01/2010"
["data"] => string(1) "A"
}
}
Upvotes: 1
Reputation: 70863
Your problem can easily be solved with a nice comparison function and uasort()
or usort()
. Here is how it works:
Your comparison function accepts two parameters, which are elements of the array you sort. Return -1 if the first parameter should appear first in the sorted array, return 1 if the second parameter should appear first, and return 0 if both are considered equal in the sorting order.
Your order criteria is like: Sort by category. If category is the same, sort by date. If date is the same, sort by data.
Unfortunately your array is not properly structured. What if another category=Value_3 appears as the last element in the array. Should it be grouped with the other Value_3 entries, or should it be sorted alone? Depending on this answer, the array should be restructured for easier sorting.
Another improvement is the way the date is stored. America date format is completely unusable for sorting, neither as a string nor as a numeric value. Either transform it to a unix timestamp, or use ISO date format "YYYY-MM-DD". Both can easily be compared without further ado.
Upvotes: 3