Reputation: 13
Where the sub arrays have similar id
s, I want to select only those with the highest date.
$array = [
['id' => 10, 'date' => '10-24-1994'],
['id' => 10, 'date' => '10-24-1996'],
['id' => 10, 'date' => '10-24-1997'],
['id' => 10, 'date' => '10-24-1998'],
['id' => 9, 'date' => '10-24-1998'],
['id' => 9, 'date' => '10-24-2001'],
['id' => 9, 'date' => '10-24-1997'],
['id' => 8, 'date' => '10-24-1996'],
['id' => 10, 'date' => '10-24-1999'],
['id' => 10, 'date' => '10-24-1991'],
['id' => 10, 'date' => '10-24-1993'],
['id' => 8, 'date' => '10-24-2001']
]; /* array i have */
$expected_Result = [
['id' => 10, 'date' => '10-24-1999'],
['id' => 9, 'date'=> '10-24-2001'],
['id' => 8, 'date' => '10-24-2001'],
];
/* array which i expected */
Upvotes: 0
Views: 1266
Reputation: 2011
I would use this as the solution, in order to have an array where the key is the id itself:
/**
* @param array{id:int, date:string} $list
*
* @return array<int,string>
*/
function sortDatesUniqueById(array $list): array
{
$result = [];
foreach ($list as ['id' => $id, 'date' => $date]) {
if (!isset($result[$id]) || $result[$id] < $date) {
$result[$id] = $date;
}
}
return $result;
}
Or another approach, to get exactly what you are asking for:
/**
* @param array{id:int, date:string} $list
*
* @return array{id:int, date:string}
*/
function sortDatesUniqueById(array $list): array
{
$result = [];
foreach ($list as ['id' => $id, 'date' => $date]) {
if (!isset($result[$id]) || $result[$id]['date'] < $date) {
$result[$id] = ['id' => $id, 'date' => $date];
}
}
return array_values($result);
}
PHPDoc used based on the standard https://github.com/phan/phan (generic arrays and array shapes).
Upvotes: 4
Reputation: 647
Here's my solution.
$result = [];
foreach ($array as $value) {
if (!in_array($value['id'], array_column($result, 'id'))) {
$result[] = $value;
} else {
foreach ($result as $key => $res) {
if ($res['id'] === $value['id'] && $value['date'] < $res['date']) {
$result[$key]['date'] = $value['date'];
}
}
}
}
First iterate over each value, if it is not in the list, add to the $result
var, else, iterate over the $result
value and check when the id is the same whith the current $value
and finally check wich date is bigger.
Upvotes: 1
Reputation: 7485
We can sort the array first by id and date ascending, and then use array_column to pull out the highest dates.
$array = [
['id' => 10, 'date' => '10-24-1994'],
['id' => 10, 'date' => '10-24-1996'],
['id' => 10, 'date' => '10-24-1997'],
['id' => 10, 'date' => '10-24-1998'],
['id' => 9, 'date' => '10-24-1998'],
['id' => 9, 'date' => '10-24-2001'],
['id' => 9, 'date' => '10-24-1997'],
['id' => 8, 'date' => '10-24-1996'],
['id' => 10, 'date' => '10-24-1999'],
['id' => 10, 'date' => '10-24-1991'],
['id' => 10, 'date' => '10-24-1993'],
['id' => 8, 'date' => '10-24-2001']
];
uasort($array, function($a, $b) {
$r = $a['id'] <=> $b['id'];
if($r == 0)
return $a['date']<=>$b['date'];
return $r;
});
var_export(array_column($array, null, 'id'));
Output:
array (
8 =>
array (
'id' => 8,
'date' => '10-24-2001',
),
9 =>
array (
'id' => 9,
'date' => '10-24-2001',
),
10 =>
array (
'id' => 10,
'date' => '10-24-1999',
),
)
Upvotes: 0
Reputation: 18557
Here is one liner,
First sort by id desc and date asc. Then make key as id so that last date of it will override every small dates. Then to reset index use array_values.
array_multisort(array_column($array, 'id'), SORT_DESC, array_column($array, 'date'), SORT_ASC, $array);
$result = array_values(array_column($array, null, "id"));
print_r($result);
array_column — Return the values from a single column in the input array
Note: column_key: The column of values to return. This value may be an integer key of the column you wish to retrieve, or it may be a string key name for an associative array or property name. It may also be NULL to return complete arrays or objects (this is useful together with index_key to reindex the array).
Output:-
Array
(
[0] => Array
(
[id] => 10
[date] => 10-24-1999
)
[1] => Array
(
[id] => 9
[date] => 10-24-2001
)
[2] => Array
(
[id] => 8
[date] => 10-24-2001
)
)
Upvotes: 0
Reputation: 12039
You can user array_multisort()
and finally array_walk()
to make the array unique.
array_multisort(
array_column($array, 'id'), SORT_DESC,
array_column($array, 'date'), SORT_DESC,
$array
);
$result = [];
array_walk($array, function ($item) use (&$result) {
!isset($result[$item['id']]) && $result[$item['id']] = $item['date'];
});
print '<pre>';
print_r($result);
Upvotes: 0
Reputation: 26460
Just loop over the array, check if that ID exists as an index in the $result
array. If it does, check if the new date is bigger than the current one - if yes, overwrite it with the new value.
$result = [];
foreach ($array as $v) {
if (!isset($result[$v['id']])) {
$result[$v['id']] = $v['date'];
} elseif ($result[$v['id']] < $v['date']) {
$result[$v['id']] = $v['date'];
}
}
Upvotes: 2