4

這裏的故事讓每個項目的索引,次數我有兩個列表:如何使用itertools.groupby()

list_one=[1,2,9,9,9,3,4,9,9,9,9,2] 
list_two=["A","B","C","D","A","E","F","G","H","Word1","Word2"] 

我想找到list_one連續9的的indicies這樣我可以得到從list_two對應的字符串,我已經試過:

group_list_one= [(k, sum(1 for i in g),pdn.index(k)) for k,g in groupby(list_one)] 

我希望得到前9的索引中的每個元組,然後嘗試從那裏走,但沒有工作..

我能做什麼h ERE? PS:我已經看了itertools的文檔,但它似乎很模糊,我.. 預先感謝

編輯: 預期輸出(鍵,occurances,index_of_first_occurance) 像

[(9, 3, 2), (9, 4, 7)] 
+3

什麼是您預期的輸出? – bozdoz

回答

5

通過您的預計產量來看,試試這個:

from itertools import groupby 

list_one=[1,2,9,9,9,3,4,9,9,9,9,2] 
list_two=["A","B","C","D","A","E","F","G","H","Word1","Word2"] 
data = zip(list_one, list_two) 
i = 0 
out = [] 

for key, group in groupby(data, lambda x: x[0]): 
     number, word = next(group) 
     elems = len(list(group)) + 1 
     if number == 9 and elems > 1: 
      out.append((key, elems, i)) 
     i += elems 

print out 

輸出:

[(9, 3, 2), (9, 4, 7)] 

但如果你真的希望像這樣的輸出:

[(9, 3, 'C'), (9, 4, 'G')] 

然後廁所k在這個片段:

from itertools import groupby 

list_one=[1,2,9,9,9,3,4,9,9,9,9,2] 
list_two=["A","B","C","D","A","E","F","G","H","Word1","Word2"] 
data = zip(list_one, list_two) 
out = [] 

for key, group in groupby(data, lambda x: x[0]): 
    number, word = next(group) 
    elems = len(list(group)) + 1 
    if number == 9 and elems > 1: 
     out.append((key, elems, word)) 

print out 
+1

'zip()'是一個更好的範例和更清晰的函數式編程,而不是生成然後傳遞巨大索引列表。 – smci

+2

我不知道你是如何破譯這個問題的,但是這看起來像是一個堅實的答案。 –

+2

微小的錯誤:它似乎檢測*任何*重複元素的組,而不僅僅是9。 – smci

2

那麼,這可能不是最完美的解決方案,但在這裏有雲:

g = groupby(enumerate(list_one), lambda x:x[1]) 
l = [(x[0], list(x[1])) for x in g if x[0] == 9] 
[(x[0], len(x[1]), x[1][0][0]) for x in l] 

這給

[(9, 3, 2), (9, 4, 7)] 
1

這看起來像一個太複雜的問題,無法融入列表理解。

element_index = 0 #the index in list_one of the first element in a group 
for element, occurrences in itertools.groupby(list_one): 
    count = sum(1 for i in occurrences) 
    yield (element, count, element_index) 
    element_index += count 

如果你想消除element_index變量,想想一個cumulative_sum功能需要做的,它的價值是依賴於已全部重複以前的值。

+0

Im得到SyntaxError:'yield'外函數 – Aous1000

+1

把上面的代碼放在函數裏面,然後調用函數。 – IceArdor

3

好的,我有oneliner解決方案。這是醜陋的,但忍耐着我。

讓我們來考慮這個問題。我們有一個我們想用itertools.groupby來總結的列表。 groupby給我們一個鍵列表和它們重複的迭代。在這個階段我們不能計算指數,但我們可以很容易地找到出現的次數。

[(key, len(list(it))) for (key, it) in itertools.groupby(list_one)] 

現在,真正的問題是我們要計算索引與舊數據的關係。在大多數在線常用功能中,我們只是在檢查當前狀態。但是,有一個功能讓我們對過去進行一瞥 - reduce

reduce是做什麼的,是通過迭代器並用該函數的最後結果和新項目執行一個函數。例如,reduce(lambda x,y: x*y, [2,3,4])將計算2 * 3 = 6,然後6 * 4 = 24並返回24.另外,您可以選擇另一個初始值來代替第一個項目。

讓我們在這裏使用它 - 對於每個項目,索引將是最後一個索引+最後一次出現的次數。爲了有一個有效的列表,我們將使用[(0,0,0)]作爲初始值。 (我們最終擺脫它)。

reduce(lambda lst,item: lst + [(item[0], item[1], lst[-1][1] + lst[-1][-1])], 
     [(key, len(list(it))) for (key, it) in itertools.groupby(list_one)], 
     [(0,0,0)])[1:] 

如果我們不會添加初始值,我們可以總結迄今出現的出現次數。

reduce(lambda lst,item: lst + [(item[0], item[1], sum(map(lambda i: i[1], lst)))], 
     [(key, len(list(it))) for (key, it) in itertools.groupby(list_one)], []) 

當然,它給了我們所有的數字。如果我們想的只是9的,我們可以包裝在filter整個事情:

filter(lambda item: item[0] == 9, ...) 
相關問題