2016-10-22 67 views
0

我需要合併兩個列表,然後計算與某個值對應的所有值。合併兩個列表並打印對應於某個值的所有值

兩個名單是:

inControl = ["False", "False", "True", "True","False", "True", "False", "True", "True", "False", "False", "False", "False", "False", "False", "True", "False", "True", "False", "False"] 

rts = [379, 396, 480, 443, 365, 280, 487, 446, 350, 367, 405, 391, 484, 359, 367, 305, 359, 479, 436, 333] 

我需要總結的所有對應於所有False值的rts,然後同爲True值(它們都是按順序)。

我已經基本上得到儘可能使用作爲zip功能的兩個列表,但我完全失去了接下來做什麼...任何幫助將不勝感激。

非常感謝:)

+0

查找到'itertools',特別到了'groupby'。請參閱該文檔[這裏](https://docs.python.org/2/library/itertools.html#itertools.groupby) –

+0

@TammoHeeren:爲'groupby':「一般情況下,迭代需求已經在整理同樣的關鍵功能「。需要在這裏對元組進行排序。 –

+0

@ Jean-FrançoisFabre好評。你絕對正確。這裏應該在'inControl'上進行排序。 –

回答

2

似乎不可思議的是,布爾值是字符串,但是...

使用zip,在匹配的元素,然後sum

(重新創建在Python 3中的其他部分中的zip因爲zip是一個可迭代)

inControl = ["False", "False", "True", "True","False", "True", "False", "True", "True", "False", "False", "False", "False", "False", "False", "True", "False", "True", "False", "False"] 

rts = [379, 396, 480, 443, 365, 280, 487, 446, 350, 367, 405, 391, 484, 359, 367, 305, 359, 479, 436, 333] 

z=zip(rts,inControl) 
sf=sum(x[0] for x in z if x[1]=='False') 
z=zip(rts,inControl) 
st=sum(x[0] for x in z if x[1]=='True') 
print(sf,st) 

結果:

5128 2783 

也許st可以利用具有sum更少字符串比較來計算:st=sum(rts)-sf(更多增加,更少的字符串比較)

變種:小環路真&假

s=dict() 

for c in ['False','True']: 
    z=zip(rts,inControl) 
    s[c]=sum(x[0] for x in z if x[1]==c) 
2

讓 - 弗朗索瓦的解決方案將工作得很好,很可讀。不過,它確實使數據傳遞了兩遍。如果名單很小,這並不是什麼大問題,但如果名單很大,可以通過一次通過大致減半操作時間。

的一個普遍做法是這樣的:

totals = {} 
for flag, value in zip(inControl, rts): 
    totals[flag] = totals.setdefault(flag, 0) + value 

此代碼不認爲inControl只有FalseTrue。它實際上可以具有任意數量的唯一值。

一種簡單的方法是使用collections模塊中的Counter類。 A Counter是一本旨在記錄計數的字典。添加兩個計數器是很明顯的事情:相同的鍵值相加。我們可以爲每對元素創建一個Counter實例,並將所有計數器相加。請注意,爲每個元素創建Counter可能是矯枉過正的 - 上述解決方案效率更高。但對於教育目的,這種解決方案是這樣的:

from collections import Counter 
counters = (Counter({k: v}) for k, v in zip(inControl, rts)) 
sum(counters, Counter()) 
+0

你的第一解決方案是非常有效的。如何通過初始化'totals = {'True':0,'False':0}來做更多的事情''。這樣,你不必在循環中調用'setdefault'。 –

0

可以產生具有單號的元組無論是在列表理解或發電機exrpession的False位置或True位置:

>>> [(e,0) if c=='False' else (0,e) for e, c in zip(rts, inControl)] 
[(379, 0), (396, 0), (0, 480), (0, 443), (365, 0), (0, 280), (487, 0), (0, 446), (0, 350), (367, 0), (405, 0), (391, 0), (484, 0), (359, 0), (367, 0), (0, 305), (359, 0), (0, 479), (436, 0), (333, 0)] 

你然後可以歸納一系列的元組與reduce

>>> reduce(lambda x, y: (x[0]+y[0], x[1]+y[1]), (((e,0) if c=='False' else (0,e) for e, c in zip(rts, inControl)))) 
(5128, 2783) 

您實際上可以使用FalseTrue布爾訪問元組:

>>> t=reduce(lambda x, y: (x[0]+y[0], x[1]+y[1]), ((e if c=='False' else 0, e if c=='True' else 0) for e, c in zip(rts, inControl))) 
>>> t[False] 
5128 
>>> t[True] 
2783 

或者,你可以使用map如果這更有意義,您:

>>> map(sum, zip(*((e,0) if c=='False' else (0,e) for e, c in zip(rts, inControl)))) 
[5128, 2783] 

或者,你可以創建一個字典與金額:

>>> dict(zip([False, True], map(sum, zip(*[(e,0) if c=='False' else (0,e) for e, c in zip(rts, inControl)])))) 
{False: 5128, True: 2783} 

如果你有大熊貓,一個偉大的方式做,這是與.groupby()sum

>>> import pandas as pd 
>>> df=pd.DataFrame({'rts':rts, 'inControl':inControl}) 
>>> df 
    inControl rts 
0  False 379 
1  False 396 
2  True 480 
3  True 443 
4  False 365 
5  True 280 
6  False 487 
7  True 446 
8  True 350 
9  False 367 
10  False 405 
11  False 391 
12  False 484 
13  False 359 
14  False 367 
15  True 305 
16  False 359 
17  True 479 
18  False 436 
19  False 333 
>>> df.groupby(inControl).sum() 
     rts 
False 5128 
True 2783 
+0

請問爲什麼要投票? – dawg

0

考慮:

inControl = ["False", "False", "True", "True","False", "True", "False", "True", "True", "False", "False", "False", "False", "False", "False", "True", "False", "True", "False", "False"] 
rts = [379, 396, 480, 443, 365, 280, 487, 446, 350, 367, 405, 391, 484, 359, 367, 305, 359, 479, 436, 333] 

我認爲inControl是一個字符串列表,而不是一個布爾值的列表。對於我的解決方案的工作,我要轉換inControl列出布爾值:

inControl = [element == 'True' for element in inControl] # ==> [False, False, ...] 

使用itertools.compress計算所有True元素的總和:

import itertools 
true_sum = sum(itertools.compress(rts, inControl)) # 2783 

現在,我們可以計算出false_sum

grand_sum = sum(rts)    # 7911 
false_sum = grand_sum - true_sum # 5128