Python 在另一个嵌套的dict列表中添加dict列表并检查父项
我试图在dict的嵌套列表中追加dict,同时检查相同的父项,然后在适当的位置追加。例如,我的输入Python 在另一个嵌套的dict列表中添加dict列表并检查父项,python,list,dictionary,yaml,Python,List,Dictionary,Yaml,我试图在dict的嵌套列表中追加dict,同时检查相同的父项,然后在适当的位置追加。例如,我的输入dicts和所需输出为: 输入: Dict1 = [{'name':'A', 'childs':[{ 'name':'B', 'childs':[{ 'name':'C', 'childs':[{
dicts
和所需输出为:
输入:
Dict1 = [{'name':'A',
'childs':[{
'name':'B',
'childs':[{
'name':'C',
'childs':[{
'name':'D',
'childs': None}]}]}]},
{'name':'E', 'childs':None}]
Dict2=[{'name':'B',
'childs':[{
'name':'C',
'childs':[{
'name':'X',
'childs':None}]}]}]
输出:-
Dict1 = [{'name':'A',
'childs':[{
'name':'B',
'childs':[{
'name':'C',
'childs':[{
'name':'D',
'childs': None},
{'name':'X' ,
'childs':None}}]}]},
{'name':'E' , 'childs':None}]
它只是将一个字典作为另一个字典的子字典进行附加,但我无法弄清楚,在两个字典中迭代时,如何检查相同的父字典,然后进行附加
def get_dict_with_name(name, list_of_dicts):
'''
returns the dict that has the same name as name from list_of_dicts
assured a dict or None
'''
if not list_of_dicts:
return None
for _dict in list_of_dicts:
if name == _dict['name']:
return _dict
# check children as well
dict_from_children = get_dict_with_name(name, _dict['childs'])
if dict_from_children:
return dict_from_children
return None
def append_stuff(list_of_dicts_1, list_of_dict_2):
'''
iter through all of list_of_dict_2, and merge with 1
'''
if not list_of_dict_2:
return
if not list_of_dicts_1:
return
for _dict in list_of_dict_2:
name = _dict['name']
dict_in_1 = get_dict_with_name(name, list_of_dicts_1)
# if u dont get a dict, simply add it as a new dict to the list
if not dict_in_1:
list_of_dicts_1.append(_dict)
continue
# if you found, now check with children - each of these children in that dict
append_stuff(dict_in_1['childs'], _dict['childs'])
它将其添加到目录1的列表中。应该这样做。
然而,由于它具有这种层次结构,也许构建一个树结构对您更有用
在您的输入中,您调用了两个列表Dict1和Dict2
所以在这里,您称为append_stuff(Dict1,Dict2)
并且Dict1具有所需的输出。1。方法说明
我提出以下方法:
从包含孩子和父母的给定词典列表生成数据库。数据库是一个字典,有助于不同元素的索引化。它包含诸如gen_base
{…,'B':{'childs':['C'],'parent':'A'},}
创建一个方法,该方法使用生成的数据库构建给定名称的树build_tree
合并数据库元素以形成完整的树merge\u from\u base
Dict1
和Dict2
成为您作为示例给出的词典列表和Dict3
所需结果
>>> base = gen_base(Dict1 + Dict2)
>>> base
{'A': {'childs': ['B'], 'parent': None},
'B': {'childs': ['C'], 'parent': 'A'},
'C': {'childs': ['D', 'X'], 'parent': 'B'},
'D': {'childs': [], 'parent': 'C'},
'E': {'childs': [], 'parent': None},
'X': {'childs': [], 'parent': 'C'}}
>>> res = merge_from_base(base=base,)
>>> res
[{'name': 'A', 'childs': [
{'name': 'B', 'childs': [
{'name': 'C', 'childs': [
{'name': 'D', 'childs': None,},
{'name': 'X', 'childs': None,}],}],}],},
{'name': 'E', 'childs': None,}]
>>> res == Dict3
True
3.来源
认真地说,Taha,这是一个稍微修改的节点类,用于构建相同的结构。我觉得这里的核心逻辑更容易理解
$> cat input.txt ( From your sample input )
{'d2': [{'childs': [{'childs': [{'childs': None, 'name': 'X'}], 'name': 'C'}], 'name': 'B'}], 'd1': [{'childs': [{'childs': [{'childs': [{'childs': None, 'name': 'D'}], 'name': 'C'}], 'name': 'B'}], 'name': 'A'}, {'childs': None, 'name': 'E'}]}
$>vi test1.py (sorry for the name, your question was too long)
class Node(object):
def __init__(self, name):
''' not making children None, [] is easier to work with '''
self.name = name
self.children = []
def add_child(self, child):
self.children.append(child)
def flatten_to_dict(self):
''' to get it back to your format '''
my_dict = {'name': self.name, 'childs': []}
for child in self.children:
my_dict['childs'].append(child.flatten_to_dict())
return my_dict
@staticmethod
def from_dict(inp_dict):
''' taking the input as dictionaries - your format converter '''
root = Node(inp_dict['name'])
if not inp_dict['childs']:
return root
for child in inp_dict['childs']:
root.add_child(Node.from_dict(child))
return root
def __repr__(self):
''' u know what this is for '''
return "%s" % self.flatten_to_dict()
def find_node_with_name(self, name):
if self.name == name:
return self
for child in self.children:
found_node = child.find_node_with_name(name)
if found_node:
return found_node
return None
@staticmethod
def merge_nodes(node1, node2):
''' the actual core logic, very simple '''
the_node = node1.find_node_with_name(node2.name)
if not the_node:
return None
for child in node2.children:
n = Node.merge_nodes(the_node, child)
if not n:
the_node.add_child(child)
return the_node
def merge_with_node(self, another_node):
''' want to return a new instance, not modify current node, so a wrapper
for a static function, one time new instance, and then modify that in place '''
# creating a new instance by deseriazling the serialized object
# since i dont want this to happen recursively, hence the wrapper
node_to_return = Node.from_dict(self.flatten_to_dict())
x = Node.merge_nodes(node_to_return, another_node)
return node_to_return
if __name__ == '__main__':
''' preprocessing, so we can work with the Node class'''
data = eval(open('input.txt').read())
d1 = data['d1'] # first list of data dicts
d2 = data['d2'] # second list of data dicts
# as per you're input example of Dict1 and Dict2
Dict1 = map(Node.from_dict, d1)
Dict2 = map(Node.from_dict, d2)
# assuming Dict2 should just be one element, then Dict2[0]
Dict2 = Dict2[0]
result = []
# try to merge with every dict in Dict1
for _dict in Dict1:
res = _dict.merge_with_node(Dict2)
result.append(res)
print result
$>python test1.py
“名称”在同一词典中是否始终唯一,或者是否可以复制?@ishez键“名称”的值在同一词典中始终唯一。Dict2中的项是否可能与Dict1的父项不同?是的。。。很好possible@ishez .. 如果两个人都有相同的父母,你会怎么做。例如,如果dict2是[{'name':'A','childs':[{'name':'B','childs':[{'name':'X','childs':None}]}]}],并且如果第一个子项在dict中不相同,那么它应该直接附加在那里,这总是正确的。。。我希望我能恰当地引用我已经写了一个更简洁的版本,有一个树状结构。如果你觉得有用,我可以在这里更新答案。给你-这段代码对我来说工作得很好,我刚刚做了一些修改,使它具有双向性。如果您能在这里发布树形结构代码,我将不胜感激。当我在公司网络中工作时,访问被拒绝。感谢这段代码,这是树遍历方法。。。。大多数情况下,yaml文件是作为配置文件创建的,我更愿意将所有内容作为子节点附加,而不必担心父节点。但这种方法展示了一种新的方法。。谢谢
$> cat input.txt ( From your sample input )
{'d2': [{'childs': [{'childs': [{'childs': None, 'name': 'X'}], 'name': 'C'}], 'name': 'B'}], 'd1': [{'childs': [{'childs': [{'childs': [{'childs': None, 'name': 'D'}], 'name': 'C'}], 'name': 'B'}], 'name': 'A'}, {'childs': None, 'name': 'E'}]}
$>vi test1.py (sorry for the name, your question was too long)
class Node(object):
def __init__(self, name):
''' not making children None, [] is easier to work with '''
self.name = name
self.children = []
def add_child(self, child):
self.children.append(child)
def flatten_to_dict(self):
''' to get it back to your format '''
my_dict = {'name': self.name, 'childs': []}
for child in self.children:
my_dict['childs'].append(child.flatten_to_dict())
return my_dict
@staticmethod
def from_dict(inp_dict):
''' taking the input as dictionaries - your format converter '''
root = Node(inp_dict['name'])
if not inp_dict['childs']:
return root
for child in inp_dict['childs']:
root.add_child(Node.from_dict(child))
return root
def __repr__(self):
''' u know what this is for '''
return "%s" % self.flatten_to_dict()
def find_node_with_name(self, name):
if self.name == name:
return self
for child in self.children:
found_node = child.find_node_with_name(name)
if found_node:
return found_node
return None
@staticmethod
def merge_nodes(node1, node2):
''' the actual core logic, very simple '''
the_node = node1.find_node_with_name(node2.name)
if not the_node:
return None
for child in node2.children:
n = Node.merge_nodes(the_node, child)
if not n:
the_node.add_child(child)
return the_node
def merge_with_node(self, another_node):
''' want to return a new instance, not modify current node, so a wrapper
for a static function, one time new instance, and then modify that in place '''
# creating a new instance by deseriazling the serialized object
# since i dont want this to happen recursively, hence the wrapper
node_to_return = Node.from_dict(self.flatten_to_dict())
x = Node.merge_nodes(node_to_return, another_node)
return node_to_return
if __name__ == '__main__':
''' preprocessing, so we can work with the Node class'''
data = eval(open('input.txt').read())
d1 = data['d1'] # first list of data dicts
d2 = data['d2'] # second list of data dicts
# as per you're input example of Dict1 and Dict2
Dict1 = map(Node.from_dict, d1)
Dict2 = map(Node.from_dict, d2)
# assuming Dict2 should just be one element, then Dict2[0]
Dict2 = Dict2[0]
result = []
# try to merge with every dict in Dict1
for _dict in Dict1:
res = _dict.merge_with_node(Dict2)
result.append(res)
print result
$>python test1.py