文章背景
根据PM的期望,我们最终需要给出归类好的数据让用户便捷查看。为啥不用MySQL的
group by
是因为数据来源是其它系统的ES结果。
前缀树的作用
trie tree
译为前缀树或字典树。因为子孙节点的前缀都一样的关系,我们可以用它做路由、单词联想、归类排序等。因为需求要为搜索页做同类分组,方便用户查看。因此思路是用
trie tree
分类然后按照子叶的后缀搜索顺序将乱掉的商品数据做排序。(看最后)
预期结果
php
$line = [
[1, 3, 2, 4, 5, 6, 7],
[2, 3, 2, 4, 5, 6, 7],
[2, 3, 1, 4, 5],
[1, 3, 2, 4, 5, 7, 6],
];
代码
php
public function insert3(array $parts, int $height, &$tree = [])
{
if (count($parts) <= $height) {
$tree['isEnd'] = true;
return;
}
$part = $parts[$height];
[$key,$child] = $this->mathChild($tree['children'], $part);
if ($height == 0 ) {
$this->warn(json_encode($tree['children']));
}
if ( ! $child) {
$child = $this->newTrie($part);
$this->insert3($parts, $height + 1, $child);
$tree['children'][] = $child;
} else {
// 下面这一段非常地重要,它决定了同级兄弟成员
$this->insert3($parts, $height + 1, $tree['children'][$key]);
}
}
public function mathChild(array $children, mixed $part)
{
foreach ($children as $key => $child) {
if ($child['part'] == $part) {
return [
$key,
$child,
];
}
}
return null;
}
private function newTrie(mixed $part): array
{
return [
'children' => [],
'isEnd' => false,
'part' => $part,
];
}
public function init()
{
$line = [
[1, 3, 2, 4, 5, 6, 7],
[2, 3, 2, 4, 5, 6, 7],
[2, 3, 1, 4, 5],
[1, 3, 2, 4, 5, 7, 6],
];
$tree = $this->newTrie('/');
foreach ($line as $item) {
$this->insert3($item, 0, $tree);
}
echo json_encode($tree, 256);
}
结果Json
ruby
{"children":[{"children":[{"children":[{"children":[{"children":[{"children":[{"children":[{"children":[],"isEnd":true,"part":7}],"isEnd":false,"part":6},{"children":[{"children":[],"isEnd":true,"part":6}],"isEnd":false,"part":7}],"isEnd":false,"part":5}],"isEnd":false,"part":4}],"isEnd":false,"part":2}],"isEnd":false,"part":3}],"isEnd":false,"part":1},{"children":[{"children":[{"children":[{"children":[{"children":[{"children":[{"children":[],"isEnd":true,"part":7}],"isEnd":false,"part":6}],"isEnd":false,"part":5}],"isEnd":false,"part":4}],"isEnd":false,"part":2},{"children":[{"children":[{"children":[],"isEnd":true,"part":5}],"isEnd":false,"part":4}],"isEnd":false,"part":1}],"isEnd":false,"part":3}],"isEnd":false,"part":2}],"isEnd":false,"part":"\/"}