我有一个CSV文件,和下图相似。我尝试用递归方式构建家庭树,但是失败了。另,我想实现一个功能比如说,通过一个家庭ID获取整个家族一共有几代人。感谢各位大牛!
你好,代码已经写好了。能够成功的生成树,请采纳,采纳后私信发给你。
先把每一行都建立成一个对象,然后去匹配关系
# -*- coding: utf-8 -*-
"""
Created on Mon Jun 28 21:03:34 2021
@author: sosome
"""
import re
a = '''10001,123456,10006,10007,10005,10003,10004,
10002,123456,10006,10007,,,,
10003,123456,10001,,10008,10010,,
10004,123456,10001,,,,,
10005,123456,,,10001,,,
10006,123456,,,10007,10001,,
10007,123456,,10009,10006,10001,,
10008,123456,,,10003,10010,,
10009,123456,,,,10007,,
10010,123456,10003,10008,,,,
'''
b = re.findall(r'[^\r\n]+',a)
c = 'PersonID,FamilyID,FatherID,MotherID,SpouseID,Children1ID,Children2ID,ChildreNID'.split(',')
def p(a):
x = a.split(',')
r = {}
for i in range(len(x)):
r[c[i]] = x[i]
r['ChildrenList'] = []
return r
f = []
for i in b:
f.append(p(i))
t = f[0]
def setParent(t,f):
l = len(f)
arr = f.copy()
for i in arr:
if i['FatherID'] == t['PersonID']:
t['ChildrenList'].append(i)
f.remove(i)
if i['PersonID'] == t['FatherID']:
f.remove(i)
i['ChildrenList'].append(t)
t = i
if t['MotherID'] == i['PersonID']:
f.remove(i)
if i['SpouseID'] == t['PersonID'] and len(t['ChildrenList'])>0:
f.remove(i)
if l == len(f):
for j in range(len(t['ChildrenList'])):
t['ChildrenList'][j] = setParent(t['ChildrenList'][j],f)
return t
else:
return setParent(t,f)
f = f[1:]
t = setParent(t,f)
#print(f)
#print(t)
def makeTree(t,lv=1):
r = {'id':t['PersonID'],'lv':lv,'child':[]}
print('* - '*lv+':'+t['PersonID'])
for i in t['ChildrenList']:
c = makeTree(i,lv+1)
r['child'].append(c)
return r
tree = makeTree(t)
#print([n['PersonID'] for n in t['arr']])
print(tree)
* - :10006
* - * - :10001
* - * - * - :10003
* - * - * - * - :10010
* - * - * - :10004
* - * - :10002
{'id': '10006', 'lv': 1, 'child': [{'id': '10001', 'lv': 2, 'child': [{'id': '10003', 'lv': 3, 'child': [{'id': '10010', 'lv': 4, 'child': []}]}, {'id': '10004', 'lv': 3, 'child': []}]}, {'id': '10002', 'lv': 2, 'child': []}]}
import re
a = '''10001,123456,10006,10007,10005,10003,10004,
10002,123456,10006,10007,,,,
10003,123456,10001,,10008,10010,,
10004,123456,10001,,,,,
10005,123456,,,10001,,,
10006,123456,,,10007,10001,,
10007,123456,,10009,10006,10001,,
10008,123456,,,10003,10010,,
10009,123456,,,,10007,,
10010,123456,10003,10008,,,,
'''
b = re.findall(r'[^\r\n]+',a)
c = 'PersonID,FamilyID,FatherID,MotherID,SpouseID,Children1ID,Children2ID,ChildreNID'.split(',')
def p(a):
x = a.split(',')
r = {}
for i in range(len(x)):
r[c[i]] = x[i]
return r
f = []
for i in b:
f.append(p(i))
f[0]['lv'] = 0
def makeLv(f):
r = []
for x in range(len(f)):
i = f[x]
if 'lv' not in i.keys():
r.append(i['PersonID'])
continue
for y in range(len(f)):
j = f[y]
if x==y:
continue
if 'lv' in j.keys():
continue
if j['SpouseID'] == i['PersonID']:
j['lv'] = i['lv']
if j['FatherID'] == i['PersonID'] or j['MotherID'] == i['PersonID']:
j['lv'] = i['lv'] + 1
if j['Children1ID'] == i['PersonID']:
j['lv'] = i['lv'] - 1
if j['Children2ID'] == i['PersonID']:
j['lv'] = i['lv'] - 1
if len(r)>0:
f = makeLv(f)
return f
f = makeLv(f)
lv = {n['PersonID']:n['lv'] for n in f}
m = min([n['lv'] for n in f])
nt = {}
for i in lv:
k = str(lv[i]+abs(m)+1)
if k in nt.keys():
nt[k].append(i)
else:
nt[k] = [i]
lv = [n for n in nt]
lv.sort()
for i in lv:
print(i,nt[i])
1 ['10009']
2 ['10006', '10007']
3 ['10001', '10002', '10005']
4 ['10003', '10004', '10008']
5 ['10010']
这个 C# winform 可以做到,这个让我在想想
1. 建立一个person类,每一列是一个属性
2. 每一行是一个对象,初始化
3. 输入一个对象,根据其属性迭代构造出对应的树关系
这个是我写的部分程序,但是弄不清楚了。
'''
Created on 2021年5月23日
@author: xiang
'''
import csv
from Person import*
#该办法去掉了重复的家庭代码,得到了一组不重复的家庭代码
def getFamilyIdList(familylist):
famlilyIdList=[]
for item in familylist:
if item not in famlilyIdList:
famlilyIdList.append(item)
return famlilyIdList
#该方法构建了一个按照家庭id分组的列表,且列表中每一个节点存储的依旧是一个家庭成员列表
def setFamilyGroup(personlist,familyIdlist):
FamilyGrouplist=[]
whole_famlilyGroupList=[]
for fid in familyIdlist:
for person in personlist:
if fid==person.fid18:
FamilyGrouplist.append(person)
whole_famlilyGroupList.append(FamilyGrouplist)
return whole_famlilyGroupList
#该方法可以会根据一个人的ID,寻找到这个人
def findPerson(personid,familylist):
me=None
for person in familylist:
if person.pid==personid:
me=person
return me
#该方法根据我这个人找到母亲
def find_mother(me,familylist):
motherID=me.pid_a_m
mother=me
for person in familylist:
if person.pid_a_m==motherID:
mother=findPerson(motherID,familylist)
else:
mother=object
if mother!=me:
print('我的ID是:'+person.pid+'我母亲的ID是:'+mother.pid)
return mother
#该方法根据我个人找到父亲
def find_father(me,familylist):
fatherID=me.pid_a_f
father=me
for person in familylist:
if person.pid_a_f==fatherID:
father=findPerson(fatherID,familylist)
else:
father=me
if father!=me:
print('我的ID是:'+person.pid+'我父亲的ID是:'+father.pid)
return father
#该方法尝试利用递归构建家庭树
def build_familyTree(me,familylist):
me=find_father(me,familylist)
build_familyTree(me,familylist)
me=find_mother(me,)
build_familyTree(me,familylist)
#这是主程序入口
if __name__ == '__main__':
with open('fmailycontmatch2.csv','r',encoding='utf-8') as f:
reader=csv.DictReader(f)
personlist=[]
familylist=[]
familyIdlist=[]
wholeFamilyGrouplist=[]
fatherlist=[]
for row in reader:
person =Person(row['fid18'],
row['pid'],
row['pid_a_f'],
row['pid_a_m'],
row['pid_a_s'],
row['pid_a_c1'],
row['pid_a_c2'],
row['pid_a_c3'],
row['pid_a_c4'],
row['pid_a_c5'])
personlist.append(person)
for person in personlist:
#将所有的人员家庭ID加入到家族列表里,这里还有重复的
familylist.append(person.fid18)
#得到一个家庭的列表
familyIdlist=getFamilyIdList(familylist)
#得到按照家庭列表的全部列表
wholeFamilyGrouplist=setFamilyGroup(personlist,familyIdlist)
for familylist in wholeFamilyGrouplist:
for me in familylist:
build_familyTree(me,familylist)
class Person(object):
class_name="被访问对象"
def __init__(self,fid18,pid,pid_a_f,pid_a_m,pid_a_s,pid_a_c1,pid_a_c2,pid_a_c3,pid_a_c4,pid_a_c5):
self.fid18=fid18
self.pid=pid
self.pid_a_f=pid_a_f
self.pid_a_m=pid_a_m
self.pid_a_s=pid_a_s
self.pid_a_c1=pid_a_c1
self.pid_a_c2=pid_a_c2
self.pid_a_c3=pid_a_c3
self.pid_a_c4=pid_a_c4
self.pid_a_c5=pid_a_c5
源数据来源于这里,https://blog.csdn.net/weixin_54194510?spm=1010.2135.3001.5343
你这问题,让我想起我2011年写过的一个家族树项目,前端用 actionscript3 + javascript + html + css,后端数据用 php写 接口返回。
原理就是把数据组装成一个无限级的层级关系数据
前段时间写过类似的需求。思路就是建立嵌套字典然后转树绘图,首先是获取父子关系,获得这个形式的数据{'parent_id':'id'}。 然后把数据塞到字典里面去,这个过程中记录递归的次数就知道有几代人了。
# 将链表数据转换为树结构数据
def list_to_tree(data_list):
res = {}
for i, v in enumerate(data):
v["parent_id"] = v["parent_id"] if v["parent_id"] else 0
res.setdefault(v['parent_id'], {}).setdefault(f"{v['id']}", v['id'])
return res
在CSDN答问题有mani吗?