Python:如何将列表拆分为字典列表?

4

我很新手,刚开始学习Python,但已经意识到自己什么都不懂。我想找到将列表拆分为字典列表的替代方法。以下是示例列表:

data = ['ID:0:0:0',
        'Status:Ok',
        'Name:PhysicalDisk0:0:0',
        'State:Online',
        'FailurePredicted:No',
        'ID:0:0:1',
        'Status:Ok',
        'Name:PhysicalDisk0:0:1',
        'State:Online',
        'FailurePredicted:No']

字典列表的最终结果:

[{'Status': 'Ok',
  'State': 'Online',
  'ID': '0:0:0',
  'FailurePredicted': 'No',
  'Name': 'PhysicalDisk0:0:0'},
 {'Status': 'Ok',
  'State': 'Online',
  'ID': '0:0:1',
  'Name': 'PhysicalDisk0:0:1',
  'FailurePredicted': 'No'}]

列表中有重复元素,需要多个字典来处理,并且列表的长度也会变化。我的代码似乎可以简化,如果我更熟悉Python的话。以下是我当前的代码:

已删除的代码 它没有工作。 :(

----------- File output as requested -------------------

# omreport storage pdisk controller=0
List of Physical Disks on Controller PERC 5/i Integrated (Embedded)

Controller PERC 5/i Integrated (Embedded)
ID                        : 0:0:0
Status                    : Ok
Name                      : Physical Disk 0:0:0
State                     : Online
Failure Predicted         : No
Progress                  : Not Applicable
Type                      : SAS
Capacity                  : 136.13 GB (146163105792 bytes)
Used RAID Disk Space      : 136.13 GB (146163105792 bytes)
Available RAID Disk Space : 0.00 GB (0 bytes)
Hot Spare                 : No
Vendor ID                 : DELL    
Product ID                : ST3146755SS     
Revision                  : T107
Serial No.                : 3LN1EF0G            
Negotiated Speed          : Not Available
Capable Speed             : Not Available
Manufacture Day           : 07
Manufacture Week          : 24
Manufacture Year          : 2005
SAS Address               : 5000C50004731C35

ID                        : 0:0:1
Status                    : Ok
Name                      : Physical Disk 0:0:1
State                     : Online
Failure Predicted         : No
Progress                  : Not Applicable
Type                      : SAS
Capacity                  : 136.13 GB (146163105792 bytes)
Used RAID Disk Space      : 136.13 GB (146163105792 bytes)
Available RAID Disk Space : 0.00 GB (0 bytes)
Hot Spare                 : No
Vendor ID                 : DELL    
Product ID                : ST3146755SS     
Revision                  : T107
Serial No.                : 3LN1EF88            
Negotiated Speed          : Not Available
Capable Speed             : Not Available
Manufacture Day           : 07
Manufacture Week          : 24
Manufacture Year          : 2005
SAS Address               : 5000C500047320B9

你能假设每个项目都恰好具有五个项目ID、状态、名称、状态和故障预测吗? - Smashery
数据里面有什么?你是怎么得到这些数据的?从文件里获取的吗?如果有的话,请展示文件格式。 - ghostdog74
@Smashery,不行。物品数量不同。 - CarpeNoctem
@ghostdog74,添加了文件输出。 - CarpeNoctem
@Smashery,不,我在分割中有“,1”。它没有起作用,因为还有另一个原因,我很难解释。如果有我的错误代码有助于解决问题,我可以把它放回去。我只是不想让人们陷入我所采取的方式。 - CarpeNoctem
5个回答

9
result = [{}]
for item in data:
    key, val = item.split(":", 1)
    if key in result[-1]:
        result.append({})
    result[-1][key] = val

请注意,result[-1] 表示“最后一个元素” - 使用负索引从末尾开始计数。 - Smashery
这就是人们所说的“Pythonic”吗?它简洁而且完美地运行。 - CarpeNoctem
是的,我会形容这个为“Pythonic”。不使用临时变量,而是直接将所有内容放入结果列表中。 - Smashery
好(且易读)的代码,虽然我个人会添加一些注释。这只是偏好问题。 - Khelben

1
import re

results = []
temp = {}
for item in data:
    (key, value) = re.search('(.*?):(.*)', item).groups()
    if temp.has_key(key): temp = {}
    temp[key] = value
    if temp not in results: results.append(temp)

这会生成一个列表的列表,我最终想要一个字典的列表以便稍后更轻松地解析。 - CarpeNoctem

1

如果你没有比“每个键的重复信号需要开始一个新字典”更多的信息,那么你的代码只能稍微改进一下,例如:

results = []
curd = {}
for x in data:
  k, v = x.split(':', 1)
  if k in curd:
    results.append(curd)
    curd = {}
  curd[k] = v
results.append(curd)

即,无需保留一个中间列表tmp,而是使用一个中间字典curd。语义上有微妙的不同--只有在键和值都相同时才会初始化一个新的字典(因此,例如'Status:Borked'这样的项将“覆盖”正在构建的'Status:Ok'),而我只将键作为标识符(因此,在这种情况下不会发生覆盖)--你确定你实现的确切语义是你所需要的吗?


“Sure”是一个强烈的词,我离它还很远——这是我的第一个Python脚本。我想要一个字典列表,以便后来迭代更容易。我不想粘贴整个脚本,因为这可能会吓跑你们乐于助人的人。 - CarpeNoctem
是的,“每个键的重复都表示需要开始一个新字典”,因为列表中key:value元素的数量可能会发生变化。这就是我试图写下来但还没有完全理解的内容。谢谢。 - CarpeNoctem

0
ret = []
ITEMS_AMOUNT = 5 
while True:
        tmp = {}
        for i in data[0:ITEMS_AMOUNT]:
                tmp.update(dict([i.split(':', 1)]))
        ret.append(tmp)

        if len(data) == ITEMS_AMOUNT:
                break
        data = data[ITEMS_AMOUNT:]

print ret 

0
d=dict([])
c=0
whatiwant=["ID","Status","Name","State","Failure Predicted"]
for line in open("file"):
    line=line.rstrip()
    sline=line.split(":",1)
    sline[0]=sline[0].strip()
    if sline[0]=="ID":
        c+=1
        d.setdefault(c,[])
    if sline[0] in whatiwant:
        d[c].append((sline[0],' '.join(sline[1:])))
for i,j in d.iteritems():
    print i,j

输出

$ ./python.py
1 [('ID', ' 0:0:0'), ('Status', ' Ok'), ('Name', ' Physical Disk 0:0:0'), ('State', ' Online'), ('Failure Predicted', ' No')]
2 [('ID', ' 0:0:1'), ('Status', ' Ok'), ('Name', ' Physical Disk 0:0:1'), ('State', ' Online'), ('Failure Predicted', ' No')]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接