algorithm - 使用图表建模家庭关系

标签 algorithm data-structures graph tree language-agnostic

我试着将家庭关系建模为一个图表,这样我就可以查询它们来找到相关的关系和其他关系。这是一个练习练习,所以我不能使用现有的解决方案,如图形数据库等等。
我试图在类似的东西之间建立一个边缘。
表示关系的实体(人)。
enter image description here
我就是这样开始的。

public class Person
{
    public string Name { get; set; }
    List<IEdge> Children { get; set; }
    IEdge Spouse { get; set; }
    IEdge Father { get; set; }
    IEdge Mother { get; set; }
}

public class Edge
{
    Person From { get; set; }
    Person To { get; set; }
    public string RelationshipType { get; set; }
}
public class Family
{
    Dictionary<string, Person> familyGraph = new Dictionary<string, Person>();
}

邻接列表表示将存储在键、值对中,来自一个人的所有边将存储在相应的个人节点中。
因此,添加与此的关系很简单。
现在说到恢复关系,比如找到兄弟姐妹,舅舅等等我需要手动导航边缘,为每种类型的关系找到合适的人。对于每一段感情,我都必须这样做。
例如,为了找到我的侄女,我必须去我的妈妈那里找我的兄弟姐妹和他们的孩子,
为了找到我的岳母。我得去找我妻子找她妈妈。
我想这就是代码在这种数据结构下的样子
List<string> FindNeice(string username)
{
    currentPerson = GerPerson(username)
    siblings = currentPerson.Mother.Children;
    niece = siblings.Where(mbox => mbox.Gender == "F").SelectMany(m => m.Children);
}

所以每段感情都要有这样的感觉是的,有些是可以重复使用的,因为母性/父性关系和你和你妻子之间交换的开始人是一样的。
我在想,是否有更好的方法来建模,以及更好的方法来编写抽取关系。

最佳答案

家庭关系看起来很简单,但很快就会变得复杂。你提到法律关系(你是妻子的母亲),但更亲密的关系是复杂的。以兄弟姐妹为例技术上:
兄弟姐妹是一个人,你和他有着相同的生母和生父。
同父异母的兄弟姐妹是一个人,你和他有着相同的生母或生父。
继兄弟姐妹是指其生母或生父与生母或生父结婚的人。
甚至不要让我开始领养关系。
但让我们暂时把这些复杂的事情放在一边,设想一个没有继兄弟、同父异母姐妹等的世界:一个简单的家谱。
建模的最灵活的方法是有一个包含关于该人的信息的Person记录,而不是关于任何关系的记录。例如,这些信息将是姓名、出生日期等,并且此人有一个永远不会更改的唯一标识符比如说,一个64位的数字。您有一个很大的Person记录表。
您还有一个很大的Relationship记录表。每个记录都包含源、目标和关系类型有两种类型的关系:父母关系和配偶关系。
(我故意把性别关系排除在这个简单的例子之外,因为它包含了不必要的复杂性,而目前关于性别身份的社会讨论使它变得更加复杂。)
因此,如果你的直系亲属由你(乔治)、你的父母(玛丽和戴夫)以及你的两个兄弟姐妹(鲍勃和萨利)组成,那么他们的关系是:

Mary, George, Parent
Dave, George, Parent
Mary, Bob, Parent
Dave, Bob, Parent
Mary, Sally, Parent
Dave, Sally, Parent
Mary, Dave, Spouse
Dave, Mary, Spouse

把它读成“玛丽是乔治的父母”。
请注意,对于是否最好包括互惠配偶关系存在一些争论我把它们放在这里是因为这样更容易推理。
所以如果你想找到一个人的兄弟姐妹,你可以这样做:
查询relationship s表,查找以该人员的ID为目标的所有关系以及关系父级的类型这会给你一个这个人父母的识别码列表。
查询所有关系的关系表,其中父项的标识符之一是源,关系类型是父项这给了你一份所有父母孩子的名单。该列表将包括原始人和所有父母的子女:根据定义,原始人的兄弟姐妹。
然后,您可以选择是要为更复杂的关系编写代码,还是为这些关系开发类似于脚本的简单定义考虑:
parents - intrinsic function
children - intrinsic function
spouse - intrinsic function
siblings - (parents children) (probably should be an intrinsic, to eliminate self)
grandparents - (parents parents)
uncles/aunts - (parents siblings)
cousins - (parents siblings children)
parents-in-law - (spouse parents)
siblings-in-law - (spouse siblings)
nieces/nephews - (siblings children) + (siblings-in-law children)

考虑到父母/子女和配偶/配偶关系,您可以轻松编写查询脚本以查找任何其他类型的家庭关系。编写代码来执行这些查询是非常容易的,如果您尝试手工编写代码,您将消除您将遇到的各种问题。
编写它就变成了编写四个内在函数(ParentsChildrenSiblingsSpouse)的问题,每个函数都接受一个IEnumerable<PersonId>参数并返回一个IEnumerable<PersonId>,然后组合这些函数Siblings函数必须从结果中排除输入参数中的任何值表亲变成:
var person = new List<PersonId> {personId};
var cousins = person.Parents().Siblings().Children();

编写代码以从我描述的简单查询定义生成这些查询并不十分困难。或者,如果您希望使用静态关系,可以为每个关系编写单独的函数。
现在,如果您想将它扩展到step-signals、half-signals等,您可以保持相同的基本关系,并添加更多信息,如relationship子类型。您仍然可以查询基本的父/子关系,但如果需要,可以过滤掉“steps”和“halfs”或其他子类型。对于性别关系,只需将性别添加到Person记录对于姐妹,查询兄弟姐妹并过滤结果以仅包含女性。
现在,如果要扩展查询定义以包含性别,则它将变成:
brother - (siblings male)
grandmother - (parents parents female)
maternal-uncle - (parents female siblings male)
spouse-step-sister - (spouse siblings step female)

关于algorithm - 使用图表建模家庭关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56519345/

相关文章:

ios - 大数据层次结构——如何实现?

recursion - Gremlin 查询以查找特定节点以任何方式连接到的整个子图

代表节点的 Svg 图像,在力有向图中改变节点大小

algorithm - 最小路径 - 所有边至少一次

algorithm - 多级遍历的数据结构

Python 回溯字符串长度 n 来自字母表 {a,b,c} 与 #a=#b

python - 在 2 个 Python 进程之间共享数据结构

Python 设置与自定义对象的区别

java - 递归打印矩阵中的所有路径

python - 用python计算每日/每周/每月的增长