"家谱"数据结构

Cas*_*Chu 6 php family-tree data-structures

我正在寻找一种用PHP表示家谱的方法.这意味着孩子需要从两个(或更多)父母那里继承.

以下是要求:

  • 1,2或更多父母
  • 如果我可以附加姓氏或关系状态等元数据,则可获得奖励积分

这是我的非工作尝试(遗憾的是没有数组作为键):

$tree = array(
    'uncle' => false, // no children
    array('mom', 'dad') => array(
        'me' => false,
        array('brother', 'sister-in-law') => array(
            'niece' => false
        )
    )
);
Run Code Online (Sandbox Code Playgroud)

问题是,我如何用这些要求代表一个家谱?

Joh*_*ica 20

你不可能在这样的单一中完成所有array()这些.您可以像这样设置树,但是设置具有多个父项和其他关系的更复杂的图需要多行代码.

如果你在这方面抛出一些OO,它会有很大的帮助.让我们创建一个Person类来帮助管理关系.从根本上说,我们有人和他们与其他人的关系,所以我们将从那里开始.

人类

我想象的是每个人都有一系列关系.该数组将首先按关系类型索引,例如"父母"或"孩子".然后每个条目都是一个Persons 数组.

class Person {
    var $name, $relations;

    function __construct($name) {
        $this->name      = $name;
        $this->relations = array();
    }

    function addRelation($type, $person) {
        if (!isset($this->relations[$type])) {
            $this->relations[$type] = array();
        }

        $this->relations[$type][] = $person;
    }

    // Looks up multiple relations, for example "parents".
    function getRelations($type) {
        if (!isset($this->relations[$type])) {
            return array();
        }

        return $this->relations[$type];
    }

    // Looks up a single relation, for example "spouse".
    function getRelation($type) {
        $relations = $this->getRelations($type);
        return empty($relations) ? null : $relations[0];
    }

    function __toString() {
        return $this->name;
    }
Run Code Online (Sandbox Code Playgroud)

友好的加法器和吸气剂

以上述为基础,我们可以添加一些更友好的方法.为了说明,我们将处理父/子关系和配偶.

    function addParents($mom, $dad) {
        $mom->addChild($this);
        $dad->addChild($this);
    }

    function addChild($child) {
        $this ->addRelation('children', $child);
        $child->addRelation('parents',  $this);
    }

    function addSpouse($spouse) {
        $this  ->addRelation('spouse', $spouse);
        $spouse->addRelation('spouse', $this);
    }

    function getParents () { return $this->getRelations('parents');  }
    function getChildren() { return $this->getRelations('children'); }
    function getSpouse  () { return $this->getRelation ('spouse');   }
}
Run Code Online (Sandbox Code Playgroud)

创造人

现在我们可以创建几个人并建立他们的关系.让我们试试比利和他的父母约翰和简.

$john  = new Person('John');
$jane  = new Person('Jane');
$billy = new Person('Billy');

$john ->addSpouse ($jane);
$billy->addParents($jane, $john);
Run Code Online (Sandbox Code Playgroud)

我们可以查看他们之间的关系:

echo "John is married to " . $john->getSpouse() . ".\n";
echo "Billy's parents are " . implode(" and ", $billy->getParents()) . ".\n";
Run Code Online (Sandbox Code Playgroud)

输出:

约翰与简结婚.
比利的父母是简和约翰.

显示家谱

如果图形变大,我们可以递归地遍历图形.这是一个示例树行走功能,它显示了一个基本的家谱.我已经添加了Sara,她的丈夫Mike和他们的儿子Bobby.

$john  = new Person('John');
$jane  = new Person('Jane');
$sara  = new Person('Sara');
$mike  = new Person('Mike');
$bobby = new Person('Bobby');
$billy = new Person('Billy');

$john ->addSpouse ($jane);
$sara ->addParents($jane, $john);
$sara ->addSpouse ($mike);
$bobby->addParents($sara, $mike);
$billy->addParents($jane, $john);

function displayFamilyTree($root, $prefix = "") {
    $parents = array($root);

    if ($root->getSpouse() != null) {
        $parents[] = $root->getSpouse();
    }

    echo $prefix . implode(" & ", $parents) . "\n";

    foreach ($root->getChildren() as $child) {
        displayFamilyTree($child, "....$prefix");
    }
}

displayFamilyTree($john);
Run Code Online (Sandbox Code Playgroud)

输出:

约翰和简
......萨拉和迈克
........鲍比
......比利


编辑:以下是@ Wrikken的评论,为了便于阅读而转载:

关于它确实.恕我直言,为每个关系添加一个从直到日期(可能是NULL,没有结束).离婚发生了,收养也是如此.另外:我会在addRelation()函数中添加一个反向类型和'ping-back' :

function addRelation($type, $person, $reverseType, $pingback = false) {
    if (!isset($this->relations[$type])) {
        $this->relations[$type] = array();
    }

    if (!in_array($person, $this->relations[$type], true)) {
        $this->relations[$type][] = $person;
    }

    if (!$pingback) {
        $person->addRelation($reverseType, $this, $type, true);
    }
}
Run Code Online (Sandbox Code Playgroud)