我正在尝试将家庭关系建模为图表,以便我可以查询它们以找到关联的关系和其他关系。这是一个练习,所以我不能使用现有的解决方案,例如图形数据库等。
我正在尝试对类似的东西进行建模,其中在相关之间存在一条边 实体(人)表示关系。
这就是我的入门方式。
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>();
}
邻接表表示将存储在键,值对中,并且来自人的所有边都将存储在相应的“人”节点中。
因此添加关系很简单。
现在,在找回关系时,例如找出兄弟姐妹,母叔叔等。我有点必须手动导航边缘以找到适合每种关系类型的合适人员。对于每种关系,我都必须做同样的事情。
例如,要找到我的外nie女,我必须走遍我的妈妈,找到我的兄弟姐妹并带上他们的孩子,
寻找我的岳母。我必须去找我的妻子找妈妈。 我在想这就是这种数据结构的代码
List<string> FindNeice(string username)
{
currentPerson = GerPerson(username)
siblings = currentPerson.Mother.Children;
niece = siblings.Where(mbox => mbox.Gender == "F").SelectMany(m => m.Children);
}
因此每个关系都必须存在。是的,有些可以重用,因为母子关系与您和妻子之间交换的始作俑者相同。
我在考虑是否有更好的方法对此建模,也有更好的方法来编写提取关系。
答案 0 :(得分:1)
家庭关系看起来是如此简单,但是它们却很快变得复杂。您提到姻亲关系(您是妻子的母亲),但更紧密的关系却很复杂。例如,考虑同级。技术上:
甚至都不要让我开始领养关系。
但是让我们暂时将这些复杂性放在一边,并假设一个没有继兄弟,同父异母姐妹等的世界:一个简单的家谱。
对此建模最灵活的方法是拥有一条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
读为“玛丽是乔治的父母”。
请注意,关于是否最好包括互惠的配偶关系存在一些争论。我将它们包括在这里是因为这样更容易推理。
因此,如果要查找某个人的兄弟姐妹,请执行以下操作:
然后,您可以选择是要为更复杂的关系编写代码,还是为这些关系开发类似于脚本的简单定义。考虑:
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)
鉴于父母/子女和配偶/配偶的关系,您可以轻松地编写查询脚本以查找任何其他类型的家庭关系。编写代码来执行这些查询非常容易,并且消除了尝试手工编码时遇到的各种问题。
编码这是写四个内在函数(Parents
,Children
,Siblings
和Spouse
)的问题,每个函数都以{ {1}}并返回IEnumerable<PersonId>
,然后组合这些函数。 IEnumerable<PersonId>
函数必须从结果中排除输入参数中的任何值。表兄弟变成:
Siblings
编写代码以根据我描述的简单查询定义生成那些查询并不是很困难。或者,如果您希望使用静态关系,则可以为每个关系编写单独的函数。
现在,如果要将其扩展到同级兄弟姐妹,半兄弟姐妹等,则可以保持相同的基本关系并添加更多信息,例如关系子类型。您仍然会查询基本的父/子关系,但是如果需要,可以过滤掉“步骤”和“半”或其他子类型。对于性别关系,只需将性别添加到var person = new List<PersonId> {personId};
var cousins = person.Parents().Siblings().Children();
记录中。对于姐妹,请查询同级并将结果过滤为仅包括雌性。
现在,如果您想扩展查询定义以包括性别,它将变成:
Person