Home > Blockchain >  Hold some values ​in position while sorting the array in PHP
Hold some values ​in position while sorting the array in PHP

Time:08-27

First I sort the items in the array by score, then I sort the items with the same score by date. However, while doing this sorting, I want a lock value greater than 0 to represent the position that item should end up in. For example: if the lock value is 5, I want it to stay in the fifth row in the array.

Here code sample...

    [0] => Array (
        [id] = 7867867,
        [sort] = 1,
        [lock] = 0,
        [score] = 322,
        [strtotime] = 16614713),
    [1] => Array (
        [id] = 7867867,
        [sort] = 2,
        [lock] = 0,
        [score] = 444,
        [strtotime] = 16614613),
    [2] => Array (
        [id] = 7867867,
        [sort] = 3,
        [lock] = 3,
        [score] = 0,
        [strtotime] = 16613713),
    [3] => Array (
        [id] = 7867867,
        [sort] = 4,
        [lock] = 0,
        [score] = 11,
        [strtotime] = 16612713),
    [4] => Array (
        [id] = 7867867,
        [sort] = 5,
        [lock] = 5,
        [score] = 0,
        [strtotime] = 16614413),
    [5] => Array (
        [id] = 7867867,
        [sort] = 6,
        [lock] = 0,
        [score] = 42,
        [strtotime] = 16614113),
    [6] => Array (
        [id] = 7867867,
        [sort] = 7,
        [lock] = 0,
        [score] = 22,
        [strtotime] = 16614013),
);

PHP Code If there is a method other than Usort, please write.

usort($array, function ($a, $b) {
    if ( $a->score == $b->score ) {  //score are same
       return $b->strtotime <=> $a->strtotime; //sort by strtotime
    }
    return $b->score <=> $a->score; //else sort by score
});

Output

    [0] => Array (
        [id] = 7867867,
        [sort] = 2,
        [lock] = 0,
        [score] = 444,
        [strtotime] = 16614613),
    [1] => Array (
        [id] = 7867867,
        [sort] = 1,
        [lock] = 0,
        [score] = 322,
        [strtotime] = 16614713),
    [2] => Array (
        [id] = 7867867,
        [sort] = 6,
        [lock] = 0,
        [score] = 42,
        [strtotime] = 16614113),
    [3] => Array (
        [id] = 7867867,
        [sort] = 7,
        [lock] = 0,
        [score] = 22,
        [strtotime] = 16614013),
    [4] => Array (
        [id] = 7867867,
        [sort] = 4,
        [lock] = 0,
        [score] = 11,
        [strtotime] = 16612713),
    [5] => Array (
        [id] = 7867867,
        [sort] = 5,
        [lock] = 5,
        [score] = 0,
        [strtotime] = 16614413),
    [6] => Array (
        [id] = 7867867,
        [sort] = 3,
        [lock] = 3,
        [score] = 0,
        [strtotime] = 16613713),
);

What I want to do:

    [0] => Array (
        [id] = 7867867,
        [sort] = 2,
        [lock] = 0,
        [score] = 444,
        [strtotime] = 16614613),
    [1] => Array (
        [id] = 7867867,
        [sort] = 1,
        [lock] = 0,
        [score] = 322,
        [strtotime] = 16614713),
    [2] => Array (
        [id] = 7867867,
        [sort] = 3,
        [lock] = 3,
        [score] = 0,
        [strtotime] = 16613713),
    [3] => Array (
        [id] = 7867867,
        [sort] = 6,
        [lock] = 0,
        [score] = 42,
        [strtotime] = 16614113),
    [4] => Array (
        [id] = 7867867,
        [sort] = 7,
        [lock] = 0,
        [score] = 22,
        [strtotime] = 16614013),
    [5] => Array (
        [id] = 7867867,
        [sort] = 5,
        [lock] = 5,
        [score] = 0,
        [strtotime] = 16614413),
    [6] => Array (
        [id] = 7867867,
        [sort] = 4,
        [lock] = 0,
        [score] = 11,
        [strtotime] = 16612713),
    
);

Is there a way to do this?

CodePudding user response:

During a sort, you have no access to the absolute position in the list, only the pair of items being compared, so I would approach it this way:

  1. Take the "locked" values out of the list
  2. Sort everything else
  3. Put the locked values back in

For step 1, just loop over array, producing two new arrays:

$result = [];
$locked = [];
foreach ( $input as $item ) {
    if ( $item['lock'] > 0 ) {
        $locked[] = $item;
    }
    else {
        $result[] = $item;
    }
}

Step 2 is the code you already have, using the array of unlocked items, which I've called $result, because it will eventually contain the final result.

For step 3, you can use array_splice to put an item into the array at a chosen position, shifting everything afterwards down.

An important thing to note here is that the order you insert in matters: if you insert item X into position 5, then item Y into position 3, position X will be shifted forward to position 6. So if your locked items aren't already in order, sort them:

usort($locked, fn($a,$b) => $a['lock'] <=> $b['lock']);

Then loop over, and splice them into their desired positions:

foreach ( $locked as $item ) {
    array_splice($result, $item['lock'], 0, $item);
}

And then you should be done :)

  • Related