2017-04-06 49 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更合適。如果我想充分發揮功能並使用更多這個庫,它可能是有道理的,但現在我寧願不爲這個函數添加依賴項。 –

相關問題