首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用图建模家庭关系

用图建模家庭关系
EN

Stack Overflow用户
提问于 2019-06-10 00:30:01
回答 1查看 1.3K关注 0票数 2

我试图将家庭关系建模为一个图表,这样我就可以查询它们以找到关联的关系和其他关系。这是一个实践练习,所以我不能使用现有的解决方案,如图形、数据库等等。

我试图建立这样的模型,在相关实体(人)之间存在一个边缘,以表示一种关系。

我就是这样开始的。

代码语言:javascript
复制
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>();
}

邻接列表表示将存储在一个键、值对中,并且来自一个人的所有边缘将存储在相应的person节点中。

因此,用它添加一种关系是很简单的。

现在说到恢复关系,比如找出兄弟姐妹,母子叔叔等等。我有点需要手动导航的边缘,以找到合适的人,为每种类型的关系。对于每一段关系,我都要做同样的事。

例如,为了找到我的侄女,我得去找我妈妈,找到我的兄弟姐妹,接他们的孩子,

因为找到了我的婆婆。我得走遍我妻子找到她妈妈。我想这就是这个数据结构的代码的样子

代码语言:javascript
复制
List<string> FindNeice(string username)
{
    currentPerson = GerPerson(username)
    siblings = currentPerson.Mother.Children;
    niece = siblings.Where(mbox => mbox.Gender == "F").SelectMany(m => m.Children);
}

所以每一段关系都要有这样的感觉。是的,有些可以重复使用,因为母子关系和你和你妻子之间交换的人是一样的。

我在想,是否有更好的方法来建模,是否有更好的方法来编写提取关系。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-06-11 05:32:41

家庭关系似乎如此简单,但它们很快就变得复杂起来。你提到了姻亲关系(你是妻子的母亲),但更亲密的关系是复杂的。例如,以兄弟姐妹为例。技术上:

  • 兄弟姐妹是一个和你有着相同亲生父母的人。
  • 同父异母是指你和他的亲生母亲或父亲同住在一起的人。
  • 异父异母是指其亲生父母与你的亲生母亲或父亲结婚的人。

别让我开始谈收养关系。

但让我们暂时抛开这些复杂的事情,设想一个没有异父异母、同父异母的世界:一个简单的家谱。

最灵活的建模方法是有一个Person记录,其中包含有关此人的信息,但不包含任何关系。例如,该信息将是姓名、出生日期等,并且该人有一个永远不会改变的唯一标识符。比如说,64位数字。您有一张大表的Person记录。

您还拥有一大张Relationship记录表。每个记录都包含源、目标和关系类型。有两种关系:父母和配偶。

(我故意把性别关系从这个简单的例子中剔除,因为包括它增加了不必要的复杂性,而目前关于性别认同的社会讨论使它变得更加复杂。)

因此,如果你的直系亲属包括你(乔治),你的父母(玛丽和戴夫),以及你的两个兄弟姐妹(鲍勃和萨利),你的关系是:

代码语言:javascript
复制
Mary, George, Parent
Dave, George, Parent
Mary, Bob, Parent
Dave, Bob, Parent
Mary, Sally, Parent
Dave, Sally, Parent
Mary, Dave, Spouse
Dave, Mary, Spouse

把它读成“玛丽是乔治的父母”

请注意,对于是否最好包括相互的配偶关系,有一些争论。我把它们包括在这里是因为这样更容易解释。

因此,如果你想找到一个人的兄弟姐妹,你可以这样做:

  1. 查询关系表中的所有关系,其中该人的ID是目标,以及关系父级的类型。这给出了一个人的父母的标识符的列表。
  2. 查询关系表中的所有关系,其中父母的标识符之一为源,关系类型为父关系。这给了你一份父母所有孩子的名单。该清单将包括原人和所有父母的子女:根据定义,原人的兄弟姐妹。

然后,您可以选择是为更复杂的关系编写代码,还是为这些关系开发简单的类似脚本的定义。考虑:

代码语言:javascript
复制
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函数必须从结果中排除输入参数中的任何值。表兄妹变成:

代码语言:javascript
复制
var person = new List<PersonId> {personId};
var cousins = person.Parents().Siblings().Children();

编写代码以从我描述的简单查询定义生成这些查询并不是非常困难的。或者,如果您更愿意使用静态关系,则可以为每个关系编写单独的函数。

现在,如果您想将其扩展到同级兄弟姐妹、同父异母等,您可以保持相同的基本关系,并添加更多的信息,如关系子类型。您仍然会查询基本的父/子关系,但如果需要,则筛选出“步骤”和“半个”或其他子类型。对于性别关系,只需在Person记录中添加性别即可。对于姐妹,查询兄弟姐妹并筛选结果,使其只包含女性。

现在,如果要扩展查询定义以包括性别,则如下所示:

代码语言:javascript
复制
brother - (siblings male)
grandmother - (parents parents female)
maternal-uncle - (parents female siblings male)
spouse-step-sister - (spouse siblings step female)
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56519345

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档