2017-04-06 52 views
3

我是新来的Python,我想编写一个函数,组列出与None信号延续项目,像这样的项目:列表中的“延续”项目。在itertools groupby关键函数中存储状态不好?

>>> g([1, None, 1, 1, None, None, 1]) 
[[1, None], [1], [1, None, None], [1]] 

我的真实数据有更复杂的项目,但我已经简化了这个问题的核心。

这是我的解决方案迄今:

import itertools 

# input 
x = [1, None, 1, 1, None, None, 1] 

# desired output from g(x) 
y = [[1, None], [1], [1, None, None], [1]] 


def f(x): 
    if x is None: 
     f.lastx = x 
    else: 
     if x != f.lastx: 
      f.counter += 1 
    return f.counter 


def g(x): 
    f.lastx = None 
    f.counter = 0 
    z = [list(g) for _, g in itertools.groupby(x, f)] 
    return z 


assert y == g(x) 

这工作,但我知道这是非常难看。

有没有更好的(更Pythonic)方法来做到这一点?例如。没有状态键功能。

回答

2

您可以结合itertools.groupbyitertools.accumulate

>>> dat = [1, None, 1, 1, None, None, 1] 
>>> it = iter(dat) 
>>> acc = accumulate(x is not None for x in dat) 
>>> [[next(it) for _ in g] for _, g in groupby(acc)] 
[[1, None], [1], [1, None, None], [1]] 

这工作,因为accumulate会给我们在每一个新组的起始intlike值增加:

>>> list(accumulate(x is not None for x in dat)) 
[True, 1, 2, 3, 3, 3, 4] 

如果你想能够处理流,只需tee迭代器。内存使用的最大增长量仅为一个组的大小。

def cgroup(source): 
    it, it2 = tee(iter(source), 2) 
    acc = accumulate(x is not None for x in it) 
    for _,g in groupby(acc): 
     yield [next(it2) for _ in g] 

这仍然给

>>> list(cgroup([1, None, 1, 1, None, None, 1])) 
[[1, None], [1], [1, None, None], [1]] 

但会更加具有无限来源:

>>> stream = chain.from_iterable(repeat([1, 1, None])) 
>>> list(islice(cgroup(stream), 10)) 
[[1], [1, None], [1], [1, None], [1], [1, None], [1], [1, None], [1], [1, None]] 
+0

哇,这是一些密集的代码。 :)我花了一些时间来了解它的工作原理,但我喜欢它,并且可以看到这种方法相当灵活。 –

+0

实际上,我只是注意到了一些......这种方法需要2遍以上的输入数据。如果数据流式传输(因为它是我的更大的问题),那么这种方法是行不通的。 :( –

+0

@BrianG:那么你不应该说你是分组*列表*项目。;-)但是处理一个流也很容易。 – DSM

1

它并不完美,因为它需要一个第三方扩展(iteration_utilities.split)和一些修修补补,但它会产生所需的输出:

>>> from iteration_utilities import split, is_not_None 

>>> lst = [1, None, 1, 1, None, None, 1] 

>>> list(split(lst, is_not_None, keep_after=True))[1:] 
[[1, None], [1], [1, None, None], [1]] 

使用这种方法需要丢弃第一个元素(因此[1:]),否则结果将以空子列表开始。

+0

谢谢你让我意识到这一点。我正在考虑某种类型的拆分可能比groupby更合适。如果我想充分发挥功能并使用更多这个库,它可能是有道理的,但现在我宁愿不为这个函数添加依赖项。 –

相关问题