php - PHP中的嵌套数据集结构
问题描述
我正在尝试在 PHP中实现嵌套数据集结构的面向对象版本(结构的另一种描述)。我已经创建了一个节点实现:
class Node
{
private $parent;
private $nodes = [];
private $level = 1;
private $left = 1;
private $right = 2;
/**
* @return self|null
*/
public function getParent()
{
return $this->parent;
}
private function setParent(self $parent = null)
{
$this->parent = $parent;
}
public function getLevel(): int
{
return $this->level;
}
private function setLevel(int $level)
{
$this->level = $level;
}
public function getLeft(): int
{
return $this->left;
}
private function setLeft(int $left)
{
$this->left = $left;
}
public function getRight(): int
{
return $this->right;
}
private function setRight(int $right)
{
$this->right = $right;
}
/**
* @return static[]
*/
public function getNodes(): array
{
return $this->nodes;
}
public function addNode(Node $new)
{
$new->setLevel($this->getLevel() + 1);
$this->nodes[] = $new;
// @todo
}
}
但是我需要帮助来实现该addNode
方法,该方法应该向当前节点添加一个新节点并更新整个树,尤其是新添加的节点、父节点、子节点等。
为了让一切变得更容易,我创建了简单的测试用例,它将检查一切是否已正确实施:
$country = new Node();
$state = new Node();
$city = new Node();
$country->addNode($state);
$state->addNode($city);
assert($country->getLeft() === 1);
assert($country->getRight() === 6);
assert($country->getLevel() === 1);
assert($state->getLeft() === 2);
assert($state->getRight() === 5);
assert($state->getLevel() === 2);
assert($city->getLeft() === 3);
assert($city->getRight() === 4);
assert($city->getLevel() === 3);
解决方案
您不应该定义父对象或对它的引用,因为您可能最终会陷入引用循环,这在代码中但在设计中并不是一件坏事,并且最终可能会使您的代码在出现问题时无法理解。
至于addNode
功能,你似乎走在了正确的轨道上,
public function addNode(Node $new)
{
//no need for getters and setters from inside the class
$new->level = $this->level + 1;
$this->nodes[] = $new;
return $this;
}
我不确定您要尝试做left
什么right
。但我认为它的顶部父母一直在左边,而底部的孩子一直在右边。在那种情况下,我只是将它与级别区分开来。
我也不会使用 private 而是使用 protected ,我在这里主要是这样做的,所以我可以一直向上走,而不需要 getter 和 setter 来使代码更紧凑,但是你可以按照你的感觉去做:
class Node
{
/**
* @var static
*/
protected $parent;
/**
* @var static[]
*/
protected $nodes = [];
/**
* @var int
*/
protected $level = 1;
/**
* @var int
*/
protected $left = 0;
/**
* @var int
*/
protected $right = 0;
public function addNode(Node $new)
{
$new->level = $this->level + 1;
$new->parent = $this;
$new->left = $new->level - 1;
if (empty($this->nodes)) {
$this->right = 1;
}
$curr = $this;
while (null !== $curr->parent) {
//walking up to the current parent and telling it there is a new level added
$curr->parent->right++;
//setting the current level 1 up
$curr = $curr->parent;
}
$this->nodes[] = $new;
return $this;
}
}
而且因为我 return $this
,我可以链接所有内容,或者嵌套 addNode 调用,例如
$country = new Node();
$state = new Node();
$city = new Node();
$country->addNode($state->addNode($city));
推荐阅读
- sql - WHERE 子句中的 SQL 日期和时间
- python - 如何解决 pygame.error: 无法打开游戏\图像\person1.png
- mysql - 使用空值对 3 个日期中最早的一个进行排序
- java - ExecutionStrategy 构造方法上的异常 java.lang.NoSuchMethodError
- django - Django - 帮助在嵌套 for 循环中显示内容
- reactjs - 如何在 React Native 中列出传入的数据
- c# - 使用 RecognizeMode.Multiple 时如何停止语音识别引擎
- amazon-web-services - 如何从来自不同区域的多个存储桶支持的 S3 提供静态 Web 内容
- python - Keras 中的 Tensorflow 亚当优化器
- php - 未显示正确的信息 PHP 和 Oracle 查询