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

Reposition element to the start of its relative sequence/group in a flat, indexed array

提问人:Chris 提问时间:10/31/2023 最后编辑:mickmackusaChris 更新时间:11/1/2023 访问量:74

问:

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

[
    ['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 排序 数组拼接

评论

2赞 Barmar 10/31/2023
请展示您尝试过的内容。我们会帮你修复它,我们不会为你写。
0赞 Barmar 10/31/2023
它应该不会比$temp = $array[$i]; $array[$i] = $array[$i+1]; $array[$i+1] = $temp;
0赞 mickmackusa 10/31/2023
在现代 PHP 中,当您使用方括号解构时,不需要变量。$temp
0赞 mickmackusa 10/31/2023
您是否曾经有过多个连续的行?这意味着,解决方案是否需要在给定的行集合中移动 3 行或更多行?Bid placed
0赞 mickmackusa 10/31/2023
在输入数组中,出价行是否始终在给定组中排在第一位?是否总是有一个最高出价来表示一系列出价行的末尾?我认为我们需要看到另一组或两组数据来了解您的输入的可变性。我预测这个问题将得到根本不同的答案,我们将无法准确地区分正确和错误的答案。

答:

1赞 mickmackusa 10/31/2023 #1

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

如果已启动的组在遇到行之前遇到非组条目,则中止该组。Max bid placed

当一个组开始并以一行适当地结束时,请删除该行并在组中的第一行之前重新注入它。函数调用将自动重新索引数组。后续的行索引将不受每次操作的影响,因为在操作之前不会增加/减少数组大小。Max bid placedMax bid placedarray_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);