我有以下Python dict:
{
'parameter_010': False,
'parameter_009': False,
'parameter_008': False,
'parameter_005': 'C<sub>MAX</sub>',
'parameter_004': 'L',
'parameter_007': False,
'parameter_006': 'R',
'parameter_001': 'Foo',
'id': 7542,
'parameter_003': 'D',
'parameter_002': 'M'
}
如图所示,有许多名为parameter_nnn
的字段,其中nnn
是一个序列号。有些是False
,其他人有值。
我想生成一个只包含parameter_nnn
字段值的列表,但只包含包含给定值的列表,按001
向上的数字排序。
因此,在这种特定情况下,所需的输出是:
["Foo", "M", "D", "L", "CMAX", "R"]
这样做的pythonic方式是什么?我显然可以开始迭代,但想知道是否有更好的东西。
Python 2.7
因此,假设您知道您正在使用JSON以及如何反序列化:
>>> import json
>>> s = """{
... "parameter_010": false,
... "parameter_009": false,
... "parameter_008": false,
... "parameter_005": "CMAX",
... "parameter_004": "L",
... "parameter_007": false,
... "parameter_006": "R",
... "parameter_001": "Foo",
... "id": 7542,
... "parameter_003": "D",
... "parameter_002": "M"
... }"""
>>> d = json.loads(s)
如果您的parameter_nnn
始终并严格遵循此格式,您可以简单地按您的要求筛选过滤的项目(因为词典排序是您想要的!):
>>> sorted([(k,v) for k, v in d.items() if v and k.startswith('parameter')])
[('parameter_001', 'Foo'), ('parameter_002', 'M'), ('parameter_003', 'D'), ('parameter_004', 'L'), ('parameter_005', 'CMAX'), ('parameter_006', 'R')]
如果您只想要这些值,只需再做一遍:
>>> [v for _,v in sorted([(k,v) for k, v in d.items() if v and k.startswith('parameter')])]
['Foo', 'M', 'D', 'L', 'CMAX', 'R']
>>>
注意,你将不得不以某种方式循环...
更易读的版本:
>>> selection = [(k,v) for k, v in d.items() if v and k.startswith('parameter')]
>>> [v for _,v in sorted(selection)]
['Foo', 'M', 'D', 'L', 'CMAX', 'R']
请注意,如果值可以是0
或您实际需要的任何其他虚假值,那么这将不起作用,例如:
>>> pprint(d)
{'id': 7542,
'parameter_001': 'Foo',
'parameter_002': 'M',
'parameter_003': 'D',
'parameter_004': 'L',
'parameter_005': 'CMAX',
'parameter_006': 'R',
'parameter_007': False,
'parameter_008': False,
'parameter_009': False,
'parameter_010': False,
'parameter_011': 0}
>>> selection = [(k,v) for k, v in d.items() if v and k.startswith('parameter')]
>>> [v for _, v in sorted(selection)]
['Foo', 'M', 'D', 'L', 'CMAX', 'R']
因此,如果你想特别过滤False
的实例(而不是0
),那么你必须使用is
:
>>> selection = [(k,v) for k, v in d.items() if v is not False and k.startswith('parameter')]
>>> [v for _, v in sorted(selection)]
['Foo', 'M', 'D', 'L', 'CMAX', 'R', 0]
这是一个解决方案:
list(zip(*sorted(i for i in d.items() if i[0].startswith('parameter') and i[1])))[1]
# ('Foo', 'M', 'D', 'L', 'C<sub>MAX</sub>', 'R')
说明
sorted
上的d.items()
返回按字典键排序的元组列表。list(zip(*..))[0]
在上一次过滤和排序后返回一个值元组。<sub></sub>
,因为我不知道它来自何处以及应该采用什么逻辑来删除这个(以及其他?)标记。import collections
dicty = {
"parameter_010": False,
"parameter_009": False,
"parameter_008": False,
"parameter_005": "CMAX",
"parameter_004": "L",
"parameter_007": False,
"parameter_006": "R",
"parameter_001": "Foo",
"id": 7542,
"parameter_003": "D",
"parameter_002": "M"
}
result = []
od = collections.OrderedDict(sorted(dicty.items()))
for k, v in od.iteritems():
if v != False and "parameter" in k:
result.append(v)
print(result)