gpt4 book ai didi

Python 递归维护键控深度

转载 作者:行者123 更新时间:2023-11-28 19:15:24 25 4
gpt4 key购买 nike

输入/目标

我的输入数据是一个 OrderedDict,它可以有一个可变深度的嵌套 OrderedDicts,所以我选择递归地处理这个输出的解析。所需的输出是带有标题的 csv。

问题的详细说明

一旦我能够正确定义 field_name 并在完成所有分支的叶子后返回分支时,我的下面的代码将起作用。 (即 Type_1.Field_3.Data 将被错误地称为 Type_1.Field_2.Field_3.Data)。

一旦 Twig 上的叶子用完了,我想从 field_name 中删除最后一个 .Field_x 以便可以添加一个新的(正确的)以下对象。

寻求帮助

有人看到我可以在哪里添加此功能吗?谢谢,

...

依赖关系:


代码片段:

def get_soql_fields(soql):
soql_fields = re.search('(?<=select)(?s)(.*)(?=from)', soql) # get fields
soql_fields = re.sub(' ', '', soql_fields.group()) # remove extra spaces
fields = re.split(',|\n|\r', soql_fields) # split on commas and newlines
fields = [field for field in fields if field != ''] # remove empty strings
return fields

def parse_output(data, soql):
fields = get_soql_fields(soql)
header = fields

master = [header]

for record in data['records']: # for each 'record' in response
row = []

for obj, value in record.iteritems(): # for each obj in record
if isinstance(value, basestring): # if query base object has desired fields
if obj in fields:
row.append(value)

elif isinstance(value, dict): # traverse down into object
path = obj
row.append(_traverse_output(obj, value, fields, row, path))
master.append(row)
return master

def _traverse_output(obj, value, fields, row, path):
for f, v in value.iteritems(): # for each item in obj
if not isinstance(v, (dict, list, tuple)):
field_name = '{path}.{name}'.format(path=path, name=f) # TODO fix this to full field name

print('FName: {0}'.format(field_name))

if field_name in fields:
print('match')
row.append(v)

elif isinstance(v, dict): # it is a dict
path += '.{obj}'.format(obj=f)
_traverse_output(f, v, fields, row, path)

Salesforce SOQL 示例:

select
Type_1.Field_1,
Type_1.Field_2.Data,
Type_1.Field_3,
Type_1.Field_4,
Type_1.Field_5.Data_1.Data,
Type_1.Field_6,
Type_2.Field_1,
Type_2.Field_2
from
Obj_1
limit
1
;

示例 Salesforce 输出:

{
"records": [
{
"attributes": {
"type": "Obj_1",
"url": "<url>"
},
"Type_1": {
"attributes": {
"type": "Type_1",
"url": "<url>"
},
"Field_1": "<stuff>",
"Field_2": {
"attributes": {
"type": "Field_2",
"url": "<url>"
},
"Data": "<data>"
},
"Field_3": "<data>",
"Field_4": "<data>",
"Field_5": {
"attributes": {
"type": "Field_2",
"url": "<url>"
},
"Data_1": {
"attributes": {
"type": "Data_1",
"url": "<url>"
},
"Data": "<data>"
}
},
"Field_6": 1.0
},
"Type_2": {
"attributes": {
"type": "Type_2",
"url": "<url>"
},
"Field_1": "<data>",
"Field_2": "<data>"
}
}
]
}

最佳答案

我为此制定了一个快速解决方案。我只会记下我的想法,并将我编写的代码附加到最后。

本质上,您的问题是您一直尝试就地修改 path,这是行不通的。而是做类似的事情

new_path = path + '.{obj}'.format(obj=f)
_traverse_output(f, v, fields, row, new_path)

关于此的注意事项:它不一定会导致值与标题的顺序相同的行(即,如果 Type_1.Field_1 位于标题列表的位置 0,则与其对应的值可能不是)。

解决此问题(以及处理一般的 csvs)的简单方法是使用 csv module 中的 DictWriter ,然后将一个空字典传递给您的第一个调用,其中键将是字段名称,值将是它们的值。

解决该问题的另一种方法是使用 None 或空字符串预填充您的行列表,然后使用 list.index 方法将值分配到适当的位置。

我写了一个 _traverse_output 的实现作为每个示例,尽管它们与您的代码略有不同。它们采用 'records' 列表的一个元素。

字典示例

def _traverse_output_with_dict(record, fields, row_values, field_name=''):
for obj, value in record.iteritems():
new_field_name = '{}.{}'.format(field_name, obj) if field_name else obj
print new_field_name
if not isinstance(value, dict):
if new_field_name in fields:
row_values[new_field_name] = value
else:
_traverse_output_with_dict(value, fields, row_values, new_field_name)

列表示例

def _traverse_output_with_list(record, fields, row, field_name=''):
while len(row) < len(fields):
row.append('')

for obj, value in record.iteritems():
new_field_name = '{}.{}'.format(field_name, obj) if field_name else obj
print new_field_name
if not isinstance(value, dict):
if new_field_name in fields:
row[fields.index(new_field_name)] = value
else:
_traverse_output_with_list(value, fields, row, new_field_name)

关于Python 递归维护键控深度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34209644/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com