
---
每年春节都有一场固定的翻车现场:饭桌上一个长辈笑眯眯看着你,你脑子里的称呼检索接口疯狂超时,最后憋出一句“那个……叔叔新年好”。
妈妈在桌下掐你大腿:那是你表姑父。
社死程度不亚于生产环境删库没备份。这种亏年年吃,今年我干脆把它当成一个算法问题解决了。
节点是人,边是关系:每条边要么是亲子(父→子),要么是婚姻(夫↔妻),没有第三种。
为什么不能用一棵树?因为树里任意两点只有一条路径,而“我—妈妈—舅舅—外婆”这种跨支路查询加上婚姻边之后,整个结构就是网状的,还带环。
边是有方向的:“爸爸的哥哥”和“哥哥的爸爸”是两条完全不同的路径。查询串本质上是一个 token 流,比如 father, brother, daughter。
你的任务就是把这条 token 流翻译成一个中文名。说人话,这就是个编译器前端:词法分析、路径折叠、语义规则匹配。
先定义 9 条原子关系:父、母、兄、弟、姐、妹、子、女、配偶。这是整个系统的字母表,别多也别少。
千万别一上来就硬编码“堂外甥”“表侄媳妇”这种字符串,为什么?组合爆炸。9 条原子关系走三步就是几百条路径,映射表手写到过年也写不完,这是最典型的硬伤。
正确姿势是分层折叠:
1. 把“爸爸的哥哥的女儿”切成 [father, brother, daughter];
2. 先折前两段:father + brother → 伯父(折叠规则带上长幼参数,哥哥是伯父、弟弟是叔父);
3. 再折 伯父 + daughter → 触发堂表判定 → 输出堂姐/堂妹。
折叠顺序很重要:从查询者这一端开始贪心折叠,每步查一次规则表,miss 了就回溯,跟正则引擎回溯是一个思路。
长幼信息从哪来?问用户,让 TA 选“对方比我大还是比我小”。别赌运气默认同龄,那一句默认值就是来年饭桌上的定时炸弹。
这是整个系统里最“玄学”的部分,拆开看其实就一条规则。
同姓为堂,异姓为表:路径中血缘跳转发生在父系男性链上(父亲的兄弟),就是堂;其余全部是表。
展开成四类:
有人问:姑姑不是爸爸那边的人吗,凭什么她孩子算表?因为姑姑的孩子姓姑父的姓,血缘上已经绕出了你们的父系宗族——判定依据是“宗族归属”,不是“过年坐在哪一桌”。
落到代码里怎么写?看折叠后的路径:第一段 == father 且第二段 == brother,打上 堂 标记,否则打 表。两行 if 的事,玄学瞬间变成 if-else。
称呼是相对的:你叫她堂姐,她叫你堂弟还是堂妹,取决于你的性别和你们的长幼关系。
这里新手最容易踩坑:把所有边反向再跑一遍算法?错。反向跑出来的是“她的视角的路径”,但你缺的不是路径,是映射。
正确做法是维护一张双向对照表:(A→B 的关系) => (B 怎么称呼 A),性别、长幼两个参数一起参与查表。
为什么不能复用正向算法?因为反向路径里长幼比较的上下文已经丢了,强行推会把“外甥”算成“侄子”这种静默 bug,上线没人报错、饭桌当场翻车,被坑惨了才知道疼。
类分型 vs 叙述型:英语亲属词只分“类别”,cousin 把性别、长幼、父系母系全部抹平;汉语是“叙述型”,每个称呼都是一条精确的路径描述。
数一下就服:堂兄堂弟堂姐堂妹 4 个,姑舅姨三系表兄弟姐妹 12 个,加上口语里的远房和姻亲,日常活跃称呼轻松过十八。
为什么汉语要分这么细?宗族社会要靠称呼干三件事:定继承顺序、划通婚边界、排尊卑座次。堂不通婚、古代表亲可通婚,称呼不精确,礼法系统直接崩。
算法视角再看一遍:英文是把所有 cousin 路径哈希进同一个桶,O(1) 返回;中文必须展开全部特征位——性别 × 长幼 × 父系/母系 × 血缘/姻亲,四维联合查询。所以英文世界几乎没人做这种工具,而我们过年真的会打开用。
伪代码级别的骨架,Python 味道:
ATOMS = {"f": "父", "m": "母", "ob": "兄",
"yb": "弟", "os": "姐", "ys": "妹",
"s": "子", "d": "女", "sp": "配偶"}
def resolve(path, my_gender, age_cmp):
node = fold(path) # 贪心折叠,miss 则回溯
tang = path[0] == "f" and path[1] in ("ob", "yb")
return build_call(node, tang, my_gender, age_cmp)
两个必踩的坑提前说:
自己写嫌麻烦也行。我后来把这套逻辑直接做成了网页版,输入“爸爸的哥哥的女儿”,秒出堂姐/堂妹加反向称呼:亲戚称呼计算器。拜年前花十分钟把爸妈两边的关系树各跑一遍,属于躺赚型的准备工作——叫对了没人夸,叫错了全场记你一年。
Q1:婶婶和舅妈总搞混,有口诀吗?
看这条婚姻边“进的是哪扇门”:进父系家门的婶婶(父亲弟弟之妻),进母系家门的舅妈(母亲兄弟之妻)。记门,别记脸。
Q2:跟我同一个姓的亲戚就一定是堂?
不一定。姑姑的孩子哪怕碰巧同姓,规则上依然是表——判定看宗族路径,不看户口本上的姓氏字段。
Q3:有没有万能公式,一个称呼都不用背?
有,就是本文的路径分解算法,它存在的意义就是消灭死记硬背。但超过三步的远房路径建议直接放弃推导——族谱数据源不准,算得再对也是垃圾进垃圾出。
评论列表 (0条)