簡體   English   中英

“家譜”數據結構

[英]“Family Tree” Data Structure

我正在尋找一種用PHP表示家譜的方法。 這意味着孩子需要從兩個 (或更多)父母那里繼承。

以下是要求:

  • 1,2或更多父母
  • 如果我可以附加姓氏或關系狀態等元數據,則可獲得獎勵積分

這是我的非工作嘗試(遺憾的是沒有數組作為鍵):

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

問題是,我如何用這些要求代表家譜?

您將無法在單個array()完成所有操作。 您可以像這樣設置樹,但是設置具有多個父項和其他關系的更復雜的圖需要多行代碼。

如果你在這方面拋出一些OO,它會有很大的幫助。 讓我們創建一個Person類來幫助管理關系。 從根本上說,我們有人和他們與其他人的關系,所以我們將從那里開始。

人類

我想象的是每個人都有一系列關系。 該數組將首先按關系類型索引,例如“父母”或“孩子”。 然后每個條目都是Person的數組。

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;
    }

友好的加法器和吸氣劑

以上述為基礎,我們可以添加一些更友好的方法。 為了說明,我們將處理父/子關系和配偶。

    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');   }
}

創造人

現在我們可以創建幾個人並建立他們的關系。 讓我們試試比利和他的父母約翰和簡。

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

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

我們可以查看他們之間的關系:

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

輸出:

約翰與簡結婚。
比利的父母是簡和約翰。

顯示家譜

如果圖形變大,我們可以遞歸地遍歷圖形。 這是一個示例樹行走功能,它顯示了一個基本的家譜。 我已經添加了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);

輸出:

約翰和簡
......薩拉和邁克
........鮑比
比利....


編輯:以下是@ 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);
    }
}

GEDCOM是一種用於在不同譜系軟件之間交換譜系數據的開放式規范。 GEDCOM文件是純文本(通常是ANSEL或ASCII),包含有關個人的系譜信息,以及將這些記錄鏈接在一起的元數據。 大多數家譜軟件支持從GEDCOM格式導入和/或導出。

使用GEDCOM的一個主要優點是,您可以使用Aldfaer(僅限荷蘭語)GrampsLegacy Family Tree等桌面程序以及Geneanet等在線工具來構建或修改您的家譜,並將其與其他家族樹進行比較。

使用GEDCOM格式的另一個主要優點是,您可以使用多種編程語言的庫來保存和加載數據。 PHP庫的示例是GEDCOM Import / Export-FilterGenealogyGedcomPHP GEDCOM

使用PHP GEDCOM,讀取和解析GEDCOM文件就像這樣簡單:

$parser = new \PhpGedcom\Parser();
$gedcom = $parser->parse('gedcom.ged');

使用GEDCOM的一個主要缺點是,GEDCOM的數據格式是圍繞核心家庭建立的,這意味着該標准僅限於支持非傳統的家庭結構,如同性伴侶,混合家庭或同居。 盡管可以擴展GEDCOM以支持這種類型的關系,但是對於這種擴展,不同軟件之間的互操作性是有限的。

使用GEDCOM的另一個主要缺點是GEDCOM文件是單片的。 如果您有數千人的數據集,或者您希望經常更改數據結構,則可能會遇到性能問題。 特別是在這些情況下,最好將數據存儲在數據庫中。 不過,這並不意味着GEDCOM毫無用處。 在這些情況下,您可能需要考慮使用基於GEDCOM格式的數據庫模式,該格式允許您在數據庫和GEDCOM格式之間導入/導出。 為此,庫也存在。 Oxy-Gen就是一個例子。


GEDCOM的替代品是GenTech的數據模型Gramps數據模型 雖然它們不像GEDCOM標准那樣常用,但它們可能更適合您的需求。

如果您想使用Gramps數據模型,您可以使用例如。 Gramps PHP導出器將您的數據導出到SQLite數據庫中。 另請參閱此源代碼 ,了解如何設計適合Gramps數據模型的數據庫。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM