如何在python中重新封装变量时使用enumerate进行列表压缩



假设我想得到二进制字符串169中每个连续1的跳跃次数,即10101001。

答案是3,2,2,因为当算法从二进制数的最右数字开始时,需要向左移动三次才能到达下一个1,两次才能到达接下来的1,依此类推

因此,该算法应该有一个计数器,从0开始,在找到0时递增1,每次达到1时重置。

我需要使用列表压缩以列表的形式输出。

这就是我目前所得到的:

number = 169
list = []
c = 1
for i in bin(number>>1)[:1:-1]:
if i == '1':
list.append(c)
c = 0
c += 1

该算法确实有效,但其想法是使用列表压缩将其转换为一行代码。我认为应该有一种使用enumerate((的方法。

就像:

n = 169
list = [i for i, c in enumerate(bin(number>>1)[:1:-1], 1) if c == '1']

问题是输出将是[3,5,7]而不是[3,2,2],因为i(索引变量(没有重置。

我正在寻找一个asnwer,它不仅仅是直接列表[a+1]-list[a],而是更优雅、更高效的解决方案。

下面是这个问题的一行代码,它很可能不可读。

s = "10101001"
result = [p - q for p, q in zip([index for index, a in enumerate(s[::-1]) if a == "1"][1:], [index for index, b in enumerate(s[::-1]) if b == "1"][:s.count("1")-1])]

您可以在此处使用groupby:

bs = "10101001"
result = [
sum(1 for _ in g) + 1  # this can also be something like len(list(g)) + 1
for k, g in groupby(reversed(bs)) 
if k == "0"
]

仅仅通过列表理解并不能很容易地做到这一点,因为你想要的东西不能通过映射/过滤(以我能想到的任何简单的方式(来表达,但一旦你有了分组迭代器,它就变成了"的长度总和;0";跑步。

您可以使用正则表达式模式轻松完成此操作

import re
out = [len(i) for i in re.findall("0*1", num)]

输出

print(out)
>>> [3, 2, 2]

最新更新