我想在单行for循环中对列表项进行赋值。
首先我有一个列表,其中每个列表项都是字典对象。然后,我在列表的每个项目上循环,并比较字典的'nodeid'字段是否为106.如果是,我将新字段添加到该字典。代码如下。
K= []
K.append({'nodeid': 100 ,'elemid': 200})
K.append({'nodeid': 106 ,'elemid': 206})
K.append({'nodeid': 107 ,'elemid': 206})
for item in K:
if item['nodeid']==106:
item['S']= [2 , 124, 123 , 3532, 35]
我想在一行中写出算法的循环部分,类似于
[item['S']=12343 for item in K if item['nodeid']==106]
但这种方法不起作用。如何在一行中编写此循环?
谢谢
正如我在评论中所说,为这项任务写一个单行程并不是一种方法,因为你失去的可读性是巨大的。
但是,如果出于纯粹的好奇心,你可以这样做:
K = [x if x['nodeid'] != 106 else dict(x, **{'S': [2 , 124, 123 , 3532, 35]}) for x in K]
这里的魔法发生在dict(x, **{'S': [2 , 124, 123 , 3532, 35]})
上,它基本上将两个dict
ion加在一起并返回它们的结果。
Python 3.5+
K = [{**d, 'S': [2 , 124, 123 , 3532, 35]} if d['nodeid'] == 106 else d for d in K]
如果你愿意,你当然可以这样做,就像这样:
K = []
K.append({'nodeid': 100 ,'elemid': 200})
K.append({'nodeid': 106 ,'elemid': 206})
K.append({'nodeid': 107 ,'elemid': 206})
K = [item if item['nodeid'] != 106 else dict(S=[2 , 124, 123 , 3532, 35], **item) for item in K]
**
是Python的“爆炸”或解包操作符的版本,在字典上使用,详细描述了over here。
但是,考虑到nodeid
,看起来您的数据已经在字典中,所以为什么不重新构建它呢?
K = {}
K[100] = {'elemid': 200}
K[106] = {'elemid': 206}
K[107] = {'elemid': 206}
K[106]['S'] = [2 , 124, 123 , 3532, 35]
这是使用散列/表数据结构的好处:快速方便(更不用说,可读)索引。每个元素的位置都是已知的,除非您有二级键标准,否则不需要对包含的元素进行任何类型的迭代。
此外,通过使用字典,您可以避免重建整个列表的成本,这通过在给定的第一个示例中使用列表推导来实现。但是请注意,如果您使用的是开头的for
循环,则不会出现此问题,因为只有在找到后才会更改元素,如果在完成操作后break
,循环将完成而不会产生任何额外费用。
如果你有很多项目,写一个单行意味着重建整个列表,如果你有稀疏的值要改变,这不是很有效。
在单行中(适用于所有版本的python> = 2.7):
K = [d if d['nodeid']!=106 else {k:v for k,v in list(d.items())+[('S',[2 , 124, 123 , 3532, 35])]} for d in K]
如果id不匹配,发出子列表,否则用子列表+额外元素构建一个字典(不使用所有python版本都没有的花哨的“字典添加”)