在Python列表推导中保持计数
在Python中,使用列表推导式时,有没有办法像在for
循环中那样使用计数器呢?
为了更清楚地说明我为什么需要计数器,来看这个例子:
初始列表:['p', 'q', 'r', 's']
想要得到的列表:[(1, 'P'), (2, 'Q'), (3, 'R'), (4, 'S')]
在想要的列表中,每个元组的第一个元素是序号。如果只是一个简单的列表,我可以用zip
来实现这个功能。但是,我现在处理的列表是嵌套的,深度有三层(可以想象成层级数据),而且是通过列表推导式生成的。
所以,我在想有没有办法在列表推导式中引入这些序号。如果没有,最好的解决方案是什么呢?
附注:这里的小写字母被转换成了大写,但这不是问题的关键,可以把它当作数据转换。
代码:
allObj = Category.objects.all()
tree =[(_, l1.name, [(__, l2.name, [(___, l3.name) for l3 in allObj if l3.parentid == l2.categoryid]) for l2 in allObj if l2.parentid == l1.categoryid]) for l1 in allObj if l1.parentid == None]
allObj
包含来自类别表的数据,这些数据以邻接表的形式表示层级数据。
我在需要序号的地方放了_
。注意,这个列表是嵌套的,所以在每一层都会有一个单独的计数器,用1、2和3个_
来表示。
8 个回答
正如其他回答中所提到的,标准库提供了一个叫做 enumerate
的功能,这意味着你可能根本不需要像下面这样的列表:
[(1, 'P'), (2, 'Q'), (3, 'R'), (4, 'S')]
因为每当你需要把字母和它在列表中的位置对应起来时,你只需要调用 enumerate
就可以了。
举个例子:
>>> low = ['p', 'q', 'r', 's']
>>> upp = [c.upper() for c in low]
>>>
>>> for i,c in enumerate(upp, 1):
... print(i,c)
...
1 P
2 Q
3 R
4 S
这只是一个例子,也许你确实需要那种列表。
我在寻找一些稍微不同的东西时,偶然发现了这个答案。
我的情况是想在列表推导式中根据某个条件来计数。为了帮助其他人,这里是我解决问题的方法:
import itertools
counter = itertools.count(0)
[(next(counter), x) for x in some_list if x != 'p']
这样,计数器只有在满足条件时才会增加,而不是每次循环都增加。
最基本的情况
[(i, x) for i, x in enumerate(some_list, 1)]
用if语句应用过滤器
[(i, x) for i, x in enumerate(some_list, 1) if i > 2]
或者像这样
[(i, x) for i, x in enumerate(some_list, 1) if x != 'p']
一点建议
大多数情况下,你其实不需要这样做。相反,你只需要在需要枚举的地方调用 enumerate(some_list, 1)
,比如在一个 for
循环中。