递归方法在迭代期间更改字典
Recursive method changing dictionary during iteration
尝试在 class 中使用递归方法来展平嵌套的 OrderedDicts。结果是
RuntimeError:字典在迭代期间改变了大小
我得到了一个 OrderedDicts 列表。大多数 OrderedDicts 都是简单的 Key:string-value 属性,但有些值反而包含另一个 OrderedDict。嵌套可以下降几层。这是一个非常简化的示例:
records = [
OrderedDict([
('rec-1_field-1', 'r1f1_value'),
('rec-1_field-2', 'r1f2_value'),
('rec-1_nest-1', OrderedDict([
('n1_field-1', 'n1f1_value'),
('n1_field-2', 'n1f2_value')
])
)
]),
OrderedDict([
...
])
]
我的目标是解除这些 OrderedDicts 的嵌套,以便上面的内容开始转换成这个(注意我试图获得的 "higherKey.lowerKey" 命名法):
flatRecords = [
{'rec-1_field-1':'r1f1_value',
'rec-1_field-2':'r1f2_value',
'rec-1_nest-1.n1_field-1':'n1f1_value',
'rec-1_nest-1.n1_field-2':'n1f2_value'},
...
]
这是我的代码的简化版本。我将每个 OrderedDict 提供给一个方法,该方法在找到嵌套的 OrderedDict 时递归。我想我正在递归中覆盖我的 flatRecord Dict 但无法确定如何更正。
class unNested():
def __init__(self):
pass
def flatResults(self, OD):
self.OD = OD
self.flattenedRecords = []
for eachRecord in self.OD:
self.flattenedRecords.append(self.flatten(eachRecord))
return self.flattenedRecords
def flatten(self, record):
self.record = record
self.flatRecord = {}
for eachKey in self.record:
if isinstance(self.record[eachKey], dict):
self.subRecord = self.flatten(self.record[eachKey])
for eachSub in self.subRecord:
self.key = eachKey + '.' + eachSub
self.flatRecord[self.key] = self.record[eachSub]
else:
self.flatRecord[eachKey] = self.record[eachKey]
return self.flatRecord
所以下面的代码片段导致 "RuntimeError: dictionary changed size during iteration"
records = [
OrderedDict([
('rec-1_field-1', 'r1f1_value'),
('rec-1_field-2', 'r1f2_value'),
('rec-1_nest-1', OrderedDict([
('rec-1_nest-1_field-1', 'r1n1f1_value'),
('rec-1_nest-1_field-2', 'r1n1f2_value')
])
)
]),
OrderedDict([
('rec-2_field-1', 'r2f1_value'),
('rec-2_field-2', 'r2f2_value'),
('rec-2_nest-1', OrderedDict([
('rec-2_nest-1_field-1', 'r2n1f1_value'),
('rec-2_nest-1_field-2', 'r2n1f2_value')
])
)
])
]
crush = unNested()
crush.flatResults(records)
我确定这是一个业余错误,但我很想听听任何想法或指导。谢谢!
可以使用扁平化的方法:
from collections import OrderedDict
records = [OrderedDict([('rec-1_field-1', 'r1f1_value'), ('rec-1_field-2', 'r1f2_value'), ('rec-1_nest-1', OrderedDict([('n1_field-1', 'n1f1_value'), ('n1_field-2', 'n1f2_value')]))])]
def flatten(d, last=''):
for a, b in d.items():
if not isinstance(b, OrderedDict):
yield (f'{last}.{a}' if last else a, b)
else:
yield from flatten(b, last = a)
final_result = dict(flatten(records[0]))
输出:
{'rec-1_field-1': 'r1f1_value', 'rec-1_field-2': 'r1f2_value', 'rec-1_nest-1.n1_field-1': 'n1f1_value', 'rec-1_nest-1.n1_field-2': 'n1f2_value'}
为列表中的每个元素创建扁平化结构:
final_result = [dict(flatten(i)) for i in records]
尝试在 class 中使用递归方法来展平嵌套的 OrderedDicts。结果是 RuntimeError:字典在迭代期间改变了大小
我得到了一个 OrderedDicts 列表。大多数 OrderedDicts 都是简单的 Key:string-value 属性,但有些值反而包含另一个 OrderedDict。嵌套可以下降几层。这是一个非常简化的示例:
records = [
OrderedDict([
('rec-1_field-1', 'r1f1_value'),
('rec-1_field-2', 'r1f2_value'),
('rec-1_nest-1', OrderedDict([
('n1_field-1', 'n1f1_value'),
('n1_field-2', 'n1f2_value')
])
)
]),
OrderedDict([
...
])
]
我的目标是解除这些 OrderedDicts 的嵌套,以便上面的内容开始转换成这个(注意我试图获得的 "higherKey.lowerKey" 命名法):
flatRecords = [
{'rec-1_field-1':'r1f1_value',
'rec-1_field-2':'r1f2_value',
'rec-1_nest-1.n1_field-1':'n1f1_value',
'rec-1_nest-1.n1_field-2':'n1f2_value'},
...
]
这是我的代码的简化版本。我将每个 OrderedDict 提供给一个方法,该方法在找到嵌套的 OrderedDict 时递归。我想我正在递归中覆盖我的 flatRecord Dict 但无法确定如何更正。
class unNested():
def __init__(self):
pass
def flatResults(self, OD):
self.OD = OD
self.flattenedRecords = []
for eachRecord in self.OD:
self.flattenedRecords.append(self.flatten(eachRecord))
return self.flattenedRecords
def flatten(self, record):
self.record = record
self.flatRecord = {}
for eachKey in self.record:
if isinstance(self.record[eachKey], dict):
self.subRecord = self.flatten(self.record[eachKey])
for eachSub in self.subRecord:
self.key = eachKey + '.' + eachSub
self.flatRecord[self.key] = self.record[eachSub]
else:
self.flatRecord[eachKey] = self.record[eachKey]
return self.flatRecord
所以下面的代码片段导致 "RuntimeError: dictionary changed size during iteration"
records = [
OrderedDict([
('rec-1_field-1', 'r1f1_value'),
('rec-1_field-2', 'r1f2_value'),
('rec-1_nest-1', OrderedDict([
('rec-1_nest-1_field-1', 'r1n1f1_value'),
('rec-1_nest-1_field-2', 'r1n1f2_value')
])
)
]),
OrderedDict([
('rec-2_field-1', 'r2f1_value'),
('rec-2_field-2', 'r2f2_value'),
('rec-2_nest-1', OrderedDict([
('rec-2_nest-1_field-1', 'r2n1f1_value'),
('rec-2_nest-1_field-2', 'r2n1f2_value')
])
)
])
]
crush = unNested()
crush.flatResults(records)
我确定这是一个业余错误,但我很想听听任何想法或指导。谢谢!
可以使用扁平化的方法:
from collections import OrderedDict
records = [OrderedDict([('rec-1_field-1', 'r1f1_value'), ('rec-1_field-2', 'r1f2_value'), ('rec-1_nest-1', OrderedDict([('n1_field-1', 'n1f1_value'), ('n1_field-2', 'n1f2_value')]))])]
def flatten(d, last=''):
for a, b in d.items():
if not isinstance(b, OrderedDict):
yield (f'{last}.{a}' if last else a, b)
else:
yield from flatten(b, last = a)
final_result = dict(flatten(records[0]))
输出:
{'rec-1_field-1': 'r1f1_value', 'rec-1_field-2': 'r1f2_value', 'rec-1_nest-1.n1_field-1': 'n1f1_value', 'rec-1_nest-1.n1_field-2': 'n1f2_value'}
为列表中的每个元素创建扁平化结构:
final_result = [dict(flatten(i)) for i in records]