2016-04-22 53 views
1

因此,我有一些來自Mongo的預計算值(按商店計算的產品的平均價格)列表。每個列表代表一個星期與不同的產品。這些清單的大小可能不同,因爲有時產品在一週內不會銷售。按店鋪平均分的子列表在兩個不同的星期之間也可以是不同的大小,因爲某些店鋪可能缺貨(因此沒有任何此產品的價格)。在Python中對不同長度的多個列表進行平均的最快方法

有沒有辦法獲得我的結果,而沒有做很多循環?

這裏是兩個星期澄清的例子:

Week1

[{u'_id': 193390, u'avgT': 12, u'avgByS': [{u'S': 7, u'avg': 12}]}, {u'_id': 193396, u'avgT': 29, u'avgByS': [{u'S': 7, u'avg': 29}, {u'S': 5, u'avg': 29}]}] 

Week2

[{u'_id': 193390, u'avgT': 11, u'avgByS': [{u'S': 7, u'avg': 10}, {u'S': 9, u'avg': 12}]}, {u'_id': 193398, u'avgT': 15, u'avgByS': [{u'S': 7, u'avg': 29}, {u'S': 5, u'avg': 29}]},{u'_id': 193396, u'avgT': 29, u'avgByS': [{u'S': 7, u'avg': 29}, {u'S': 5, u'avg': 29}]}] 

所需的輸出

[{u'_id': 193390, u'avgT': 11.5, u'avgByS': [{u'S': 7, u'avg': 11}, {u'S': 9, u'avg': 12}]}, {u'_id': 193398, u'avgT': 15, u'avgByS': [{u'S': 7, u'avg': 29}, {u'S': 5, u'avg': 29}]},{u'_id': 193396, u'avgT': 29, u'avgByS': [{u'S': 7, u'average': 29}, {u'S': 5, u'average': 29}]}] 
+0

你想要什麼從列表中以平均?如果你只關心一個具體的價值,那麼長度並不重要。另外,for循環有什麼問題? –

+0

如果產品在兩週內出現('_id'出現在兩個列表中),如果來自同一家商店,我需要平均價格('平均值')(=如果相同'avgByS.S')。如果對於一種產品,我在一週內有兩家商店的價格,第二週期間有一家商店的價格(這家商店也在前一週),這個價格在兩週內取平均值。另一個保持不變(在這個例子中不是2)。 –

+0

for循環的問題是我有成千上萬的產品,最終的計算不一定在兩週內完成,但可能從一週到很多(最可能在52/53之間,等於一年)。因此,它很慢,許多imbricated循環 –

回答

0

有沒有一種方法來獲得我的結果,而不是做很多for循環?

不可以。您的數據結構是list-within-list。沒有...迭代就無法迭代數據。

但嵌套for循環並不總是一個壞主意!一些嵌套for循環會導致O(N^2)行爲,但是一些嵌套for循環會導致O(N)行爲,這取決於您的實際代碼。

以下是計算您的數據的一種方法。請注意,它有三個嵌套for循環。你無法避免這種情況。但是沒有一個嵌套的循環導致多項式複雜性。我在big-O上生鏽了,但我聲稱在O(N)中運行以下程序中的聚合循環,其中N是avgByS列表中的值的總數。 (第二循環的複雜性將等同於第一,但我呼籲sorted()上的結果,這可能會減緩下來一些。)

from __future__ import division 
from pprint import pprint 

weeks = [ 
    [{u'_id': 193390, u'avgT': 12, u'avgByS': [{u'S': 7, u'avg': 12}]}, {u'_id': 193396, u'avgT': 29, u'avgByS': [{u'S': 7, u'avg': 29}, {u'S': 5, u'avg': 29}]}], 
    [{u'_id': 193390, u'avgT': 11, u'avgByS': [{u'S': 7, u'avg': 10}, {u'S': 9, u'avg': 12}]}, {u'_id': 193398, u'avgT': 15, u'avgByS': [{u'S': 7, u'avg': 29}, {u'S': 5, u'avg': 29}]},{u'_id': 193396, u'avgT': 29, u'avgByS': [{u'S': 7, u'avg': 29}, {u'S': 5, u'avg': 29}]}] 
] 

# First, accumlate the data. Convert lists to dicts. 
total = {} 
for week in weeks: 
    for product in week: 
     total_product = total.setdefault(
      product['_id'], 
      { 
       u'_id':product['_id'], 
       u'avgT':[], 
       u'avgByS':{} 
      }) 
     total_product['avgT'].append(product['avgT']) 
     for store in product['avgByS']: 
      total_product['avgByS'].setdefault(store['S'],[]).append(store['avg']) 
pprint (total) 

# Next, convert dicts to lists and compute averages. 
averages = [{ 
    u'_id': k, 
    u'avgT': sum(v['avgT'])/len(v['avgT']), 
    u'avgByS': [{ 
     u'S': kk, 
     u'avg': sum(vv)/len(vv), 
     } 
     for kk,vv in sorted(v['avgByS'].items())] 
    } 
    for k,v in sorted(total.items())] 
pprint(averages) 
+0

謝謝,我會盡快找到答案。我會將其標記爲已接受(因爲我不知道什麼時候可以檢查它)。 –

相關問題