在树结构中给出重复的数组分支唯一的id?

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

这是我第三次尝试问这个问题,对前两次写得不好表示歉意,我希望这能澄清问题。

我将树结构部分存储在数据库中,并在 SQL 函数中检索它们,这是从数据库返回的数组:

$res = array(
    array("uid" => "244", "part_id" => "259", "parent_part_id" => ""),
    array("uid" => "245", "part_id" => "260", "parent_part_id" => "259"),
    array("uid" => "246", "part_id" => "261", "parent_part_id" => "259"),
    array("uid" => "247", "part_id" => "230", "parent_part_id" => "259"),
    array("uid" => "248", "part_id" => "233", "parent_part_id" => "259"),
    array("uid" => "249", "part_id" => "40", "parent_part_id" => "260"),
    array("uid" => "251", "part_id" => "40", "parent_part_id" => "261"),
    array("uid" => "252", "part_id" => "257", "parent_part_id" => "233"),
    array("uid" => "250", "part_id" => "257", "parent_part_id" => "40"),
    array("uid" => "254", "part_id" => "258", "parent_part_id" => "257")
);
//Wanted output:
$res = array(
    array("uid" => "244", "part_id" => "259", "parent_part_id" => ""),
    array("uid" => "245", "part_id" => "260", "parent_part_id" => "259"),
    array("uid" => "246", "part_id" => "261", "parent_part_id" => "259"),
    array("uid" => "247", "part_id" => "230", "parent_part_id" => "259"),
    array("uid" => "248", "part_id" => "233", "parent_part_id" => "259"),
    array("uid" => "249", "part_id" => "40", "parent_part_id" => "260"),
    array("uid" => "251", "part_id" => "40.2", "parent_part_id" => "261"),
    array("uid" => "250", "part_id" => "257", "parent_part_id" => "40"),
    array("uid" => "254", "part_id" => "258", "parent_part_id" => "257"),
    array("uid" => "250.2", "part_id" => "257.2", "parent_part_id" => "40.2"),
    array("uid" => "254.2", "part_id" => "258.2", "parent_part_id" => "257.2"),
    array("uid" => "252", "part_id" => "257.3", "parent_part_id" => "233"),
    array("uid" => "254.3", "part_id" => "258.3", "parent_part_id" => "257.3")
);

这是我尝试过的在线 php 脚本, 我无法弄清楚我哪里出错了,所以请随意撕开这个脚本: https://onlinephp.io/c/2893d

这是我用来运行输入数组的类:

class UniqueParts
{

    public function __construct($input)
    {
        $this->input_array = $input;
        $this->return_array = [];
        $this->exists = [];
    }

    function returnUniquePartArray()
    {
        //Loop through array
        foreach ($this->input_array as $i) {
            //if it's the first part occurrence, add to exists array and increase count by 1
            if (!isset($this->exists[$i['part_id']])){
                $this->exists[$i['part_id']] = 1;
                $this->return_array[] = $i;
            } else {
                $this->exists[$i['part_id']] += 1;
                $this->loopAndDuplicate($i['part_id'], $this->exists[$i['part_id']]);
                $i['part_id'] = $i['part_id'].'.'.$this->exists[$i['part_id']];
                $this->return_array[] = $i;
            }
        }
        return $this->return_array;
    }


    private function loopAndDuplicate($pid, $count){
        foreach ($this->input_array as $i){
            if ($i['parent_part_id'] == $pid){
                if (isset($this->exists[$i['part_id']])) {
                    $this->exists[$i['part_id']] += 1;
                } else {
                    $this->exists[$i['part_id']] = 1;
                }
                    $this->loopAndDuplicate($i['part_id'], $this->exists[$i['part_id']]);
                    if ($this->exists[$i['part_id']] > 1) {
                        $i['parent_part_id'] = $pid.'.'.$count;
                        $i['part_id'] = $i['part_id'] . '.' . $this->exists[$i['part_id']];
                    }
                    $this->return_array[] = $i;
            }
        }
    }

}

转换为树结构后,如下所示:

 uid = 244
 part_id = 259
 parent_part_id = 

   uid = 245
   part_id = 260
   parent_part_id = 259
  
     uid = 249
     part_id = 40
     parent_part_id = 260
    
       uid = 250
       part_id = 257
       parent_part_id = 40
      
         uid = 254
         part_id = 258
         parent_part_id = 257
        
   uid = 246
   part_id = 261
   parent_part_id = 259
  
     uid = 251
     part_id = 40
     parent_part_id = 261
    
       uid = 250
       part_id = 257
       parent_part_id = 40
      
         uid = 254
         part_id = 258
         parent_part_id = 257
        
   uid = 247
   part_id = 230
   parent_part_id = 259
  
   uid = 248
   part_id = 233
   parent_part_id = 259
  
     uid = 252
     part_id = 257
     parent_part_id = 233
    
       uid = 254
       part_id = 258
       parent_part_id = 257

它正确地复制分支,但是我需要为重复的部分和分支提供唯一的part_id,然后为子级提供唯一的parent_part_id。这是我想要的打印方式:

 uid = 244
 part_id = 259
 parent_part_id = 

   uid = 245
   part_id = 260
   parent_part_id = 259
  
     uid = 249
     part_id = 40
     parent_part_id = 260
    
       uid = 250
       part_id = 257
       parent_part_id = 40
      
         uid = 254
         part_id = 258
         parent_part_id = 257
        
   uid = 246
   part_id = 261
   parent_part_id = 259
  
     uid = 251
     part_id = 40.2
     parent_part_id = 261
    
       uid = 250.2
       part_id = 257.2
       parent_part_id = 40.2
      
         uid = 254.2
         part_id = 258.2
         parent_part_id = 257.2
        
   uid = 247
   part_id = 230
   parent_part_id = 259
  
   uid = 248
   part_id = 233
   parent_part_id = 259
  
     uid = 252
     part_id = 257.3
     parent_part_id = 233
    
       uid = 254.3
       part_id = 258.3
       parent_part_id = 257.3

这是我从中返回树的数据库的 SQL。我想添加这些唯一标识符的原因是因为我使用的小部件 (jqwidgets) 在其树小部件中存在缺陷,因为它需要每个部分 id 键都是唯一的,以便将它们分类为单独的行。

WITH RECURSIVE generation AS (
SELECT part_id,
uid,
parent_part_id
FROM test.part_linked
WHERE
uid = 244
UNION ALL
SELECT child.part_id,
child.uid,
child.parent_part_id
FROM test.part_linked child
JOIN generation g
ON g.part_id = child.parent_part_id
)
SELECT DISTINCT generation.uid,
generation.part_id,
generation.parent_part_id
FROM generation LEFT join
test.part ON generation.part_id = part.part_id;

我尝试了多个版本的递归但无济于事。我也尝试过使用 MySQL 来做到这一点,但我的知识还不够好。

php oop recursion multidimensional-array tree
1个回答
0
投票

因此,在您的

loopAndDuplicate
函数中,您正在修改
$i['part_id']
以附加计数值,但当您递归调用该函数时,它不会被保留。也许这会导致不正确的
part_id
值。

$i['part_id'] = $i['part_id'].'.'.$this->exists[$i['part_id']];

如果我对你的问题的理解没有错误,那么你定义的递归函数就不必要地复杂,并且使得跟踪计数和父部件 ID 变得困难。
因此保持构造函数相同,你可以尝试这样的事情。 在

returnUniquePartArray
中,我们从根开始处理节点。

public function returnUniquePartArray() {
    $this->return_array = [];
    $this->exists = [];
    $this->processNode('', '');
    return $this->return_array;
}

还有递归函数

processNode
-

private function processNode($parentId, $newParentPartId) {
    foreach ($this->input_array as $i) {
        if ($i['parent_part_id'] == $parentId) {
            $partId = $i['part_id'];

            if (isset($this->exists[$partId])) {
                $count = $this->exists[$partId]++;
                $i['part_id'] = $partId . '.' . $count;
            }

            $i['parent_part_id'] = $newParentPartId;
            $this->return_array[] = $i;

            $this->processNode($partId, $i['part_id']);
        }
    }
}

因此,它在这里迭代输入数组以查找

parent_part_id
等于当前
$parentId
的节点,并且对于每个匹配节点,它检查
part_id
是否已存在于
$this->exists
数组中。 if 条件处理唯一性,确保重复的 part_id 具有唯一值。 希望这有帮助

© www.soinside.com 2019 - 2024. All rights reserved.