Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Move specific array items to beginning of array without altering order of the rest

I have an array:

Array
(
    [product1] => Array
    (
        [id] => 1
        [title] => 'p1'
        [extra] => Array(
            [date] => '1990-02-04 16:40:26'
        )
    )

    [product2] => Array
    (
        [id] => 2
        [title] => 'p2'
        [extra] => Array(
            [date] => '1980-01-04 16:40:26'
        )
    )
    [product3] => Array
    (
        [id] => 3
        [title] => 'p3'
        [extra] => Array(
            [date] => '2000-01-04 16:40:26'
        )
    )
    [product4] => Array
    (
        [id] => 4
        [title] => 'p4'
        [extra] => Array(
            [date] => '1995-01-04 16:40:26'
        )
    )
    [product5] => Array
    (
        [id] => 5
        [title] => 'p5'
        [extra] => Array(
            [date] => '1960-01-04 16:40:26'
        )
    )
    ...

I need to get 2 products with the latest date and move them to the start of the array.

I've looked into the multisort function, and I could sort the array like this, but then the entire array would be arranged by date, I want to maintain the order of the array but just bump up the latest 2 rows.

I need to pick out the 2 latest (order by date) from the array, then move these to the start of the array. So the order of the ids should be:

3,4,1,2,5

The latest 2 have been moved to the front of the array, the remainder are still ordered by id.

like image 609
panthro Avatar asked Nov 10 '22 12:11

panthro


1 Answers

Not the most optimal implementation, but the most straight forward:

$array = /* your data */;

$latest = $array;
uasort($latest, function (array $a, array $b) {
    return strtotime($a['extra']['date']) - strtotime($b['extra']['date']);
});
array_splice($latest, 2);

$latestOnTop = array_merge($latest, array_diff_key($array, $latest));

The array_splice operation requires that your array keys are actually product1 or similar; won't work with numeric indices, as they'll be renumbered. Use another truncation mechanism if that's the case.

If your array is really big, a complete sort will be unnecessarily slow. In that case, you should rather loop over the array once, keeping track of the two latest items (and their keys) you could find, then array_diff_key and array_merge on that. That's a bit more difficult to implement (left as exercise for the reader), but much more efficient.

like image 193
deceze Avatar answered Nov 14 '22 21:11

deceze