2

我有一个看起来像这样的零和一个列表:

lst = [0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1]

我怎样才能把这个 lst 变成这个:

transformed_lst = lst = [0, 1, 1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 3, 0, 4, 4]

基本上,在每次出现 1 时,将其转换为 n+1 整数。我确信使用 itertools/groupby/functools 有一种优雅的方法可以做到这一点。这是一个尝试,但并不完全正确:

from itertools import cycle

ints = cycle(range(len(lst))) 
transformed_lst = [next(ints) if i != 0 in lst else 0 for i in lst]  

>>> [0, 0, 1, 2, 3, 0, 0, 0, 4, 5, 0, 0, 0, 6, 0, 7, 8]  
4

6 回答 6

6

您基本上有两种状态-“正在读取0s”和“正在读取1s”-当您在 then(即从 1 到 0)之间切换时,将应用于后续1s 更改的增量:

reading_zeroes = True
delta = 0
for x in input:
    if x:
        reading_zeroes = False
        x += delta
    elif not reading_zeroes:
        delta += 1
        reading_zeroes = True
    yield x
于 2012-11-27T18:39:56.167 回答
3

使用itertools.count(),itertools.chain()itertools.groupby():

In [14]: from itertools import *

In [15]: c=count(1)

In [16]: lis=[0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1]

In [17]: list(chain(*[list(g) if k!=1 else [next(c)]*len(list(g)) for k,g in groupby(lis)]))

Out[17]: [0, 1, 1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 3, 0, 4, 4]

在这里你也可以使用sum(1 for _ in g)代替len(list(g))

根据要求,使用生成器功能的可读版本:

In [27]: def func(l):
    c=count(1)
    for k,g in groupby(l):
        if k==1:
            for x in [next(c)]*sum(1 for _ in g):
                yield x
        else:
            for x in g:
                yield x
   ....:                 

In [28]: list(func(lis))
Out[28]: [0, 1, 1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 3, 0, 4, 4]
于 2012-11-27T18:33:37.903 回答
3

请注意,当当前元素为 1 且前一个元素为 0 时,您只有“下一个组”。

previous = 0
grp = 0
for elem in lst:
    if elem and not previous:
         grp += 1
    previous = elem
    yield (grp if elem else 0)
于 2012-11-27T19:00:50.703 回答
2
>>> lst = [0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1]
>>> from itertools import groupby
>>> [i//2 if k else 0 for i, (k, g) in enumerate(groupby(lst), 2) for j in g]
[0, 1, 1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 3, 0, 4, 4]
于 2012-11-27T18:52:43.803 回答
0
>>> lst = [0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1]
>>> transformed = []
>>> idx = 1
>>> for key, grp in groupby(lst):
...    if key:
...       transformed += [idx] * len(list(grp))
...       idx += 1
...    else:
...       transformed += list(grp)
... 
>>> transformed
[0, 1, 1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 3, 0, 4, 4]
>>> 
于 2012-11-27T18:40:31.533 回答
0

我发现这是可读性和简洁性之间的良好结合(不需要跟踪状态):

from itertools import groupby

def transform(numbers):
    counter = 0
    for value, iterator in groupby(numbers):
        if value:
            counter += 1

        for i in iterator:
            if value:
                yield counter
            else:
                yield 0

pre_transformed = [0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1]
print list(transform(pre_transformed))

返回:

[0, 1, 1, 1, 1, 0, 0, 0, 2, 2, 0, 0, 0, 3, 0, 4, 4]
于 2012-11-27T18:52:00.293 回答