将元素重新定位到平面索引数组中其相对序列/组的开头

问题描述 投票:0回答:1

假设我有一个数组,例如:

[
    ['action' => 'Created', 'timestamp' => '2023-10-30 20:51:57.284602'],
    ['action' => 'Updated', 'timestamp' => '2023-10-30 20:51:57.284603'],
    ['action' => 'Started', 'timestamp' => '2023-10-30 20:51:57.284604'],
    ['action' => 'Bid placed', 'timestamp' => '2023-10-30 20:51:57.284605'],
    ['action' => 'Max bid placed', 'timestamp' => '2023-10-30 20:51:57.284606'],
    ['action' => 'Bid placed', 'timestamp' => '2023-10-30 20:51:57.284607'],
    ['action' => 'Max bid placed', 'timestamp' => '2023-10-30 20:51:57.284608'],
    // and so on...
    ['action' => 'Ended', 'timestamp' => '2023-10-30 20:51:57.284609'],
],

我需要交换所有“出价”项目与“最高出价”项目的顺序。可能没有任何“最高出价”项目。数组中也可能有很多这样的条目。

例如

[
    ['action' => 'Created', 'timestamp' => '2023-10-30 20:51:57.284602'],
    ['action' => 'Updated', 'timestamp' => '2023-10-30 20:51:57.284603'],
    ['action' => 'Started', 'timestamp' => '2023-10-30 20:51:57.284604'],
    ['action' => 'Max bid placed', 'timestamp' => '2023-10-30 20:51:57.284606'],
    ['action' => 'Bid placed', 'timestamp' => '2023-10-30 20:51:57.284605'],
    ['action' => 'Max bid placed', 'timestamp' => '2023-10-30 20:51:57.284608'],
    ['action' => 'Bid placed', 'timestamp' => '2023-10-30 20:51:57.284607'],
    // and so on...
    ['action' => 'Ended', 'timestamp' => '2023-10-30 20:51:57.284609'],
],

我已经尝试过一些事情,但似乎总是以以下顺序结束:

[
    ['action' => 'Created'],
    ['action' => 'Updated'],
    ['action' => 'Started'],
    ['action' => 'Max bid placed'],
    ['action' => 'Max bid placed'],
    ['action' => 'Bid placed'],
    ['action' => 'Bid placed'],
    // and so on...
    ['action' => 'Ended'],
],

这真的可能吗?

php arrays sorting array-splice
1个回答
1
投票

迭代时,缓存给定组的起点。

如果已启动的组在遇到

Max bid placed
行之前遇到非组条目,则中止该组。

当一个组开始并以

Max bid placed
行适当结束时,删除
Max bid placed
行并在组中的第一行之前将其重新注入。该数组将通过
array_splice()
函数调用自动重新索引。后续行索引将不受每次操作的影响,因为在操作之前数组大小不会增加/减少。

代码:(演示

$start = null;
foreach ($array as $i => $row) {
    if ($row['action'] === 'Bid placed') {
        $start ??= $i;  // only store the first $i in the group
        continue;
    }
    if ($start !== null && $row['action'] === 'Max bid placed') {
        array_splice($array, $start, 0, array_splice($array, $i, 1)); // prune and reinsert row
    }
    $start = null;
}
var_export($array);

我最初考虑过,但放弃了以下方法,因为对于有条件移动数组中的单行这一相对简单的过程来说,它需要太多的排序和内存。

//                          DON'T USE THIS CODE, IT IS NOT CORRECT.
$grouper = [];
$actions = [];
$timestamps = [];
$i = 0;
foreach ($array as $row) {
    $grouper[] = $i;
    $actions[] = $row['action'];
    $timestamps[] = $row['timestamp'];
    $i += $row['action'] !== 'Bid placed';
}
array_multisort($grouper, $actions, SORT_DESC, $timestamps, $array);
var_export($array);
© www.soinside.com 2019 - 2024. All rights reserved.