2013-01-12 23 views
0

我有一個應該做以下的功能:取一個列表的列表,以及數字權重列表。然後,採用列表中每個底層項目的加權平均值,權重列表中的第一個項目用於加權第一個列表中的項目,權重列表中的第二個項目用於加權第二個列表等等。它就像一個函數,它簡單地取得列表中項目的加權平均值,但項目被分組,以便將特定權重應用於每個組。如果很多東西具有相同的重量,這很有用。下面是代碼:減少()似乎並不返回一個數字,否則的.index()無法正常工作像它應該

def getAverage(x,wts=[0.1,0.3,0.6]): 
    """Get weighted average of partitioned list.""" 
    xsum = 0 
    i = 0 
    for item in x: 
     xsum += reduce(lambda x,y:x+y,item)*wts[i] 
     i += 1 
    return xsum/reduce(lambda x,y:x+y,wts) 

然而,當我嘗試編譯,我得到以下錯誤該行:

TypeError: unsupported operand type(s) for +=: 'int' and 'list' 

什麼?爲什麼?爲什麼該乘法返回一個列表?這是沒有意義的。 reduce()返回一個數字(精確的整數),並且wts的元素是浮點數。如何不允許添加到xsum?我誤用lambda還是什麼?

+1

您需要顯示'x'的內容。它看起來也許'x'是列表的列表。 – BrenBarn

+0

'x' *是列表的列表。這是該功能的目的。那就是:'[90,97,75,92],[88,40,94],[75,90]' – mszegedy

+3

你對我的代碼工作正常,返回'3.3'就此致電:'getAverage( [[1,2,3],[2,3,4]])' –

回答

4

你的功能主要是聲音(雖然我相信它是命名錯了,或者你想通過項目的末過於數量來劃分 - 否則它不是平均值),所以你必須傳遞不正確的參數。最有可能的是,你的第二個參數實際上是列表的列表,而不是整數列表。

這就是說,我們可以改善的功能。這裏有幾個問題。首先,您使用reduce()來彙總項目,當the sum() built-in可以更有效地完成這項工作。

接下來,循環計數使用i - 這是一個不好的做法,相反,我們應該使用the enumerate() built-in。但是,我們在這裏使用它來同時循環兩個列表,而在Python中,最好使用the zip built-in來完成。

其結果是被累積的,我們可以把整個事情變成generator expression,總結這一點。這意味着我們可以結束了這樣的一個簡單的方法:

def weighted_average(items, weights): 
    total = sum(sum(item)*weight for item, weight in zip(items, weights)) 
    return total/sum(weights) 

我也留下了對權重的默認值 - 除非默認爲特定領域,我建議有沒有很好的默認位置,如它取決於items的長度。唯一可能的好的違約可能是推定相同的權重。例如:

def weighted_average(items, weights=None): 
    if not weights: 
     weights = [1]*len(items) 
    total = sum(sum(item)*weight for item, weight in zip_longest(items, weights)) 
    return total/sum(weights) 
相關問題