如何筛选数组以仅包含每个id的最新项?


How can I filter an array to include only the most recent items for each id?

我有一个像下面这样的数组:

Array
(
    [0] => Array
        (
            [clearing] => 160000
            [paydate] => 2016-08-03
            [latecharge] => 900
        )
    [1] => Array
        (
            [clearing] => 160000
            [paydate] => 2016-08-04
            [latecharge] => 950
        )
    [2] => Array
        (
            [clearing] => 160001
            [paydate] => 2016-08-05
            [latecharge] => 850
        )
)

我试图保留每个清除的最新paydate,并删除数组的其余部分。

例如,对于清除160000,最新的paydate是2016-08-04,对于160001,最新的paydate是2016-08-05,所以我的结果数组应该如下所示:

Array
(
    [1] => Array
        (
            [clearing] => 160000
            [paydate] => 2016-08-04
            [latecharge] => 950
        )
    [2] => Array
        (
            [clearing] => 160001
            [paydate] => 2016-08-05
            [latecharge] => 850
        )
)

我该怎么做?

遍历数组并按'clearing'键分组。每次你得到一个'clearing'没有在你的结果数组中设置,将其设置为当前实例,或者如果它被设置,如果当前实例是较新的,替换它。

foreach ($clearings as $clearing) {
    $id = $clearing['clearing'];
    if (!isset($latest[$id]) || $latest[$id]['paydate'] < $clearing['paydate']) {
        $latest[$id] = $clearing;
    }
}

@jeroen的评论说得很好。例如,如果您(或将来的读者)从数据库中获取这个数组,那么修改查询并在数据库中执行此操作可能会更有效。这个概念被称为群最大,在这个问题上有一些很好的答案,有几种不同的方法。

创建一个遍历数组的函数。

function clearOldPaydates($array)
{
    $cleaned = array();
    foreach($array as $item)
    {
        // if it's the first item of this date we keep it
        // if there is already an item with this date we only overwrite it if it's older
        if(!isset($cleaned[$item['paydate']])
            || strtotime($item['paydate']] > $cleaned[$item['paydate'])
        {
            $cleaned[$item['paydate']] = $item;
        }
    }
    // we return the array with numeric keys
    return array_values($cleaned);
}