分组算法(支持PHP和Laravel Collection)



我需要一些关于分组算法的帮助。。。我在Laravel集合中有一些对象,下面是json表示的一些示例数据:

[
{
"group": "WHITE",
"name": "John Doe",
"sequence": 1
},
{
"group": "WHITE",
"name": "John Doe Jr",
"sequence": 2
},
{
"group": "BLUE",
"name": "John Doe Sr",
"sequence": 3
},
{
"group": "BLUE",
"name": "John Doe Again",
"sequence": 4
},
{
"group": "RED",
"name": "Mr John Doe",
"sequence": 5
},
{
"group": "RED",
"name": "Ms Joahnna Doe",
"sequence": 6
},
{
"group": "BLUE",
"name": "Dr Johnny Doe",
"sequence": 7
},
{
"group": "RED",
"name": "Sir John Doe",
"sequence": 8
},
{
"group": "RED",
"name": "Sir John Doe Senior",
"sequence": 9
},
{
"group": "WHITE",
"name": "Ms John Doe",
"sequence": 10
}
]

我希望能够按组名对这些对象进行分组,但保持序列不变,并在出现两次或两次以上的地方重复键,如下图所示:

{
"WHITE": [
{ "name": "John Doe", "sequence": 1 },
{ "name": "John Doe Jr", "sequence": 2 }
],
"BLUE": [
{ "name": "John Doe Sr", "sequence": 3 },
{ "name": "John Doe Again", "sequence": 4 }
],
"RED": [
{ "name": "Mr John Doe", "sequence": 5 },
{ "name": "Ms Joahnna Doe", "sequence": 6 }
],
"BLUE (second group)": [
{ "name": "Dr Johnny Doe", "sequence": 7 }
],
"RED (second group)": [
{ "name": "Sir John Doe", "sequence": 8 },
{ "name": "Sir John Doe Senior", "sequence": 9 }
],
"WHITE (second group)": [
{ "name": "Ms John Doe",  "sequence": 10 }
]
}

我已经找到了这样做的方法:我迭代每个对象,寻找序列号不重要的前一个对象中的occurrence,并在满足前一个条件时向更改此名称的对象添加一个新的group_name键(即添加我发现的拆分计数(。。。据我记忆所及,推送原始集合中的每一个事件让我可以使用一个简单的$collection->groupBy('group_name')

foreach ($data as $stop) {
$previous_stops_in_group = $stops
->where('group', $stop->group)
$stop->group_name = $stop->group;
$stop->splitted = false;
if ($previous_stops_in_group->count() >0) {
$last_sequence_in_group = $previous_stops_in_group->last()->sequence;
if (($stop->sequence - $last_sequence_in_group) > 1) {
$splittedroutes++;
$stop->group_name = $stop->group . $splittedroutes;
$stop->splitted = true;
}
}

$last_splitted_group = $stops
->where('splitted',true)
->where('stop_group',$stop->stop_group)
->where('direction', $stop->direction)->last();
if (!empty($last_splitted_group) && isset($last_splitted_group->group_name)) {
$stop->group_name = $last_splitted_group->group_name;
}
$stops->push($stop);
}

不幸的是,我在大约一年前写了这本糟糕的杰作,现在我不知道发生了什么,因为这个算法应该应用于数百条记录,但它并没有相应地工作。

我想找到一个更可预测的解决方案,使用表达性语法,也许使用集合的本地方法,也许是partition()mergeRecursive()的组合?

有人能给我指个方向吗?我真的很挣扎很累。。。

提前感谢,我真丢脸!:(

我不知道集合是否可以做得更好,但我的方法是:

$items = [
{
"group": "WHITE",
"name": "John Doe",
"sequence": 1
},
// ...
{
"group": "WHITE",
"name": "Ms John Doe",
"sequence": 10
}
];
$result = [];
foreach ($items as $item) {
if (!isset($result[$item['group']])) $result[$item['group']] = [];
$result[$item['group']][] = [
'name' => $item['item'],
'sequence' => $item['sequence'],
];
}

最新更新