我尝试练习Python练习,但使用列表理解来解决问题而不是本书中显示的初学者样式循环。有一个例子,它要求将一个数字列表放入偶数列表中,但是它们必须在子列表中,这样如果数字跟随一个而不被奇数中断,它们应该放在一起进入子列表:
my_list = [2,3,5,7,8,9,10,12,14,15,17,25,31,32]
desired_output = [[2],[8],[10,12,14],[32]]
所以你可以在上面所需的输出中看到,10,12,14是彼此跟随的均匀而不被奇数打断,所以它们一起被放入子列表中。 8在它的两边都有一个奇数,因此在消除赔率后它会被单独放入一个子列表。
我可以使用下面的列表理解轻松地组合一个evens列表,但是我不知道如何将它放入像所需输出节目那样的子列表中。有人可以使用列表理解(或生成器,我不会介意,因为我现在正在尝试学习这两者)来建议这个想法。谢谢!
evens = [x for x in my_list if x%2==0]
print(evens)
[2, 8, 10, 12, 14, 32]
答案 0 :(得分:3)
正如评论中所解释的那样,列表推导不应被视为"对于初学者而言#34; - 首先关注使用简单的for
循环编写逻辑。
当您准备就绪时,您可以查看基于理解的方法。这是一个:
from itertools import groupby
my_list = [2,3,5,7,8,9,10,12,14,15,17,25,31,32]
condition = lambda x: all(i%2==0 for i in x)
grouper = (list(j) for _, j in groupby(my_list, key=lambda x: x%2))
res = filter(condition, grouper)
print(list(res))
# [[2], [8], [10, 12, 14], [32]]
在此解决方案中需要注意的要点是,在调用list(res)
之前,不会计算任何内容。这是因为filter
和生成器理解是懒惰的。
答案 1 :(得分:2)
您提到也想学习生成器,所以这里的版本也更具可读性,imho。
from itertools import groupby
def is_even(n):
return n%2 == 0
def runs(lst):
for even, run in groupby(lst, key=is_even):
if even:
yield list(run)
if __name__ == '__main__':
lst = [2, 3, 5, 7, 8, 9, 10, 12, 14, 15, 17, 25, 31, 32]
res = list(runs(lst))
print(res)
顺便说一句,如果你绝对,积极地希望将它作为列表理解来实现,那么这个解决方案很自然地脱离了上述:
[list(run) for even, run in groupby(lst, key=is_even) if even]
答案 2 :(得分:1)
如果你不想使用itertools,还有另一种方法可以使用列表推导。
首先,取奇数元素的索引:
=IF(COUNTIF(U12, "A*") > 0, "Yes", "No")
并添加两个标记:[i for i,x in enumerate(my_list) if x%2==1]
之前和[-1]
之后:
[len(my_list)]
你现在有类似的东西:
odd_indices = [-1]+[i for i,x in enumerate(my_list) if x%2==1]+[len(my_list)]
# [-1, 1, 2, 3, 5, 9, 10, 11, 12, 14]
你可以看到你的序列。现在,取这些指数之间的元素。要做到这一点,请将 [2,3,5,7,8,9,10,12,14,15,17,25,31,32]
^---^-^-^---^-----------^--^--^--^----^
与自身压缩以获得区间作为元组:
odd_indices
您只需要过滤非空列表:
zip(odd_indices, odd_indices[1:])
# [(-1, 1), (1, 2), (2, 3), (3, 5), (5, 9), (9, 10), (10, 11), (11, 12), (12, 14)]
even_groups = [my_list[a+1:b] for a,b in zip(odd_indices, odd_indices[1:])]
# [[2], [], [], [8], [10, 12, 14], [], [], [], [32]]
您可以将这两个步骤合并为一个理解列表,但这有点不可读:
even_groups = [my_list[a+1:b] for a,b in zip(odd_indices, odd_indices[1:]) if a+1<b]
# [[2], [8], [10, 12, 14], [32]]
正如@jpp所指出的那样,在你感到舒服之前,首选基本循环。也许永远避免那些嵌套列表理解......