【发布时间】:2018-06-20 16:23:20
【问题描述】:
我有一个 CSV 文件,其标题如下:
cpus/0/compatible clocks/HSE/compatible ../frequency memories/flash/compatible ../address ../size [and so on...]
我能够将该标题解析为嵌套字典,如下所示:
{'clocks': {'HSE': {'compatible': '[1]',
'frequency': '[2]'}},
'cpus': {'0': {'compatible': '[0]'}},
'memories': {'bkpsram': {'address': '[13]',
'compatible': '[12]',
'size': '[14]'},
'ccm': {'address': '[7]',
'compatible': '[6]',
'size': '[8]'},
'flash': {'address': '[4]',
'compatible': '[3]',
'size': '[5]'},
'sram': {'address': '[10]',
'compatible': '[9]',
'size': '[11]'}},
'pin-controller': {'GPIOA': {'enabled': '[16]'},
'GPIOB': {'enabled': '[17]'},
'GPIOC': {'enabled': '[18]'},
'GPIOD': {'enabled': '[19]'},
'GPIOE': {'enabled': '[20]'},
'GPIOF': {'enabled': '[21]'},
'GPIOG': {'enabled': '[22]'},
'GPIOH': {'enabled': '[23]'},
'GPIOI': {'enabled': '[24]'},
'GPIOJ': {'enabled': '[25]'},
'GPIOK': {'enabled': '[26]'},
'compatible': '[15]'}}
(它是一个dict 对象,用pprint() 打印)
类似于'[<number>]' 的键的值反映了 CSV 文件中应该从中加载数据的列的索引。
由于我主要使用 C/C++,我实际上很想在 Python 中使用指针/引用,因为那时我只需在每个值中放置一个指向列表元素的指针,并且对于每一行我可以修改列表内容,但我认为在 Python 中没有办法轻易获得这种行为。
所以现在我打算将这个字典转储到一个字符串中,并连续执行以下 3 次修改:
- 将
{替换为{{, - 将
}替换为}}, - 将
'[<number>]'替换为{<number>}。
之后,我将能够使用类似 ast.literal_eval(dictAsStr.format(*rowFromCsv)) 的内容“加载”数据,但是将整个字典转换为字符串然后再转换回字典似乎是浪费时间......
我在这里错过了其他一些明显的解决方案吗? CSV 的格式和我加载标题的方式不是固定的,我可以很容易地改变它,但是 我真的想要一个不会归结为“递归访问每个键并从当前行加载适当的值”的解决方案手动”。
从 CSV 文件中,我将每一行加载为字符串列表,例如:
['["ARM,Cortex-M4", "ARM,ARMv7-M"]',
'["ST,STM32-HSE", "fixed-clock"]',
'0',
'["on-chip-flash"]',
'0x8000000',
'131072',
'',
'',
'',
'["on-chip-ram"]',
'0x20000000',
'65536',
'',
'',
'',
'["ST,STM32-GPIOv2-pin-controller"]',
'False',
'False',
'False',
'',
'',
'',
'',
'False',
'',
'',
'']
现在我想将每个加载的行(字符串列表)中的值插入到嵌套字典中的适当键中,因此按照上面的示例,我想得到:
{'clocks': {'HSE': {'compatible': '["ST,STM32-HSE", "fixed-clock"]',
'frequency': '0'}},
'cpus': {'0': {'compatible': '["ARM,Cortex-M4", "ARM,ARMv7-M"]'}},
'memories': {'bkpsram': {'address': '',
'compatible': '',
'size': ''},
'ccm': {'address': '',
'compatible': '',
'size': ''},
'flash': {'address': '0x8000000',
'compatible': '["on-chip-flash"]',
'size': '131072'},
'sram': {'address': '0x20000000',
'compatible': '["on-chip-ram"]',
'size': '65536'}},
'pin-controller': {'GPIOA': {'enabled': 'False'},
'GPIOB': {'enabled': 'False'},
'GPIOC': {'enabled': 'False'},
'GPIOD': {'enabled': ''},
'GPIOE': {'enabled': ''},
'GPIOF': {'enabled': ''},
'GPIOG': {'enabled': ''},
'GPIOH': {'enabled': 'False'},
'GPIOI': {'enabled': ''},
'GPIOJ': {'enabled': ''},
'GPIOK': {'enabled': ''},
'compatible': '["ST,STM32-GPIOv2-pin-controller"]'}}
为了完整起见,这里是我要加载的 CSV 文件的前几行。第一列不是上面介绍的字典的一部分,因为它用于索引。
chip,cpus/0/compatible,clocks/HSE/compatible,../frequency,memories/flash/compatible,../address,../size,memories/ccm/compatible,../address,../size,memories/sram/compatible,../address,../size,memories/bkpsram/compatible,../address,../size,pin-controller/compatible,pin-controller/GPIOA/enabled,pin-controller/GPIOB/enabled,pin-controller/GPIOC/enabled,pin-controller/GPIOD/enabled,pin-controller/GPIOE/enabled,pin-controller/GPIOF/enabled,pin-controller/GPIOG/enabled,pin-controller/GPIOH/enabled,pin-controller/GPIOI/enabled,pin-controller/GPIOJ/enabled,pin-controller/GPIOK/enabled
STM32F401CB,"[""ARM,Cortex-M4"", ""ARM,ARMv7-M""]","[""ST,STM32-HSE"", ""fixed-clock""]",0,"[""on-chip-flash""]",0x8000000,131072,,,,"[""on-chip-ram""]",0x20000000,65536,,,,"[""ST,STM32-GPIOv2-pin-controller""]",False,False,False,,,,,False,,,
STM32F401CC,"[""ARM,Cortex-M4"", ""ARM,ARMv7-M""]","[""ST,STM32-HSE"", ""fixed-clock""]",0,"[""on-chip-flash""]",0x8000000,262144,,,,"[""on-chip-ram""]",0x20000000,65536,,,,"[""ST,STM32-GPIOv2-pin-controller""]",False,False,False,,,,,False,,,
STM32F401CD,"[""ARM,Cortex-M4"", ""ARM,ARMv7-M""]","[""ST,STM32-HSE"", ""fixed-clock""]",0,"[""on-chip-flash""]",0x8000000,393216,,,,"[""on-chip-ram""]",0x20000000,98304,,,,"[""ST,STM32-GPIOv2-pin-controller""]",False,False,False,,,,,False,,,
用于解析头部的代码:
import csv
with open("some-path-to-CSV-file") as csvFile:
csvReader = csv.reader(csvFile)
header = next(csvReader)
previousKeyElements = header[1].split('/')
dictionary = {}
for index, key in enumerate(header[1:]):
keyElements = key.split('/')
i = 0
while keyElements[i] == '..':
i += 1
keyElements[0:i] = previousKeyElements[0:-i]
previousKeyElements = keyElements
node = dictionary
for keyElement in keyElements[:-1]:
node = node.setdefault(keyElement, {})
node[keyElements[-1]] = '[{}]'.format(index)
【问题讨论】:
-
你能展示你的示例输出吗?
-
@Rakesh - 你有什么示例输出?没有可用的最终输出,因为我仍然想知道如何很好地加载它,但是 - 为简单起见 - CSV 中的值可以被认为只是字符串。因此,我正在寻找一种方法,将字典值中的“标签”替换为从 CSV 文件中的后续行加载的实际字符串。稍后我将粘贴几行 CSV 文件,但是当作为文本查看时,这真的很“密集”...
-
"由于我主要使用 C/C++,我实际上很想在 Python 中使用指针/引用,因为我只需在每个值中放置一个指向列表元素的指针,并且对于每一行我可以修改列出内容,但我认为在 Python 中无法轻松获得这种行为。” => 我不清楚您在这里要做什么,但是如果您解释了您要解决的 real 问题,而不是您认为的解决方案,我们可能会建议使用 pythonic解决方案。
-
@brunodesthuilliers - 是的,我正在寻找 Pythonic 解决方案。我只是描述了我想到的解决方案,仅此而已。问题是“将字符串列表中的值(这是我从 CSV 行中得到的)加载到嵌套字典(这是我最终想要的)中的干净方法,可能不需要递归访问每个键并加载手动值(因为这是一个明显的解决方案 (; )"。
-
@FreddieChopin 是的,我明白这一点 - 我不明白你真正想要做什么(你想要解决什么问题)。您能否至少为您发布的 csv 提取添加一个预期的最终输出示例?
标签: python csv dictionary nested mapping