2009-11-09 168 views
4

我目前有一個結構是字典:每個值是一個包含數值的列表。這些數字列表中的每一個都包含了什麼(借用SQL習語),您可以調用包含前三個值的主鍵:一年,玩家標識符和團隊標識符。這是字典的關鍵。Python數據結構推薦?

所以,你可以通過傳遞一個值的一年,玩家ID獲得的唯一行,和團隊ID如下:

statline = stats[(2001, 'SEA', 'suzukic01')] 

其中產量像

[305, 20, 444, 330, 45] 

我d喜歡改變這個數據結構,以便通過這三個鍵中的任何一個快速求和:因此,您可以通過傳入年份,球員ID和球隊ID之一,輕鬆地在數字列表中分割給定索引的總和,然後指數。我希望能夠做類似

hr_total = stats[year=2001, idx=3] 

其中3的idx對應於將檢索的數字列表中的第三列。

任何想法?

回答

4

閱讀數據倉庫。任何書。

閱讀上星型架構設計。任何書。認真。

你有幾個方面:年,球員,團隊。

你有一個事實:得分

你想有這樣的結構。

然後,您要創建一組這樣的尺寸指標。

years = collections.defaultdict(list) 
players = collections.defaultdict(list) 
teams = collections.defaultdict(list) 

您的事實表可以是這個collections.namedtuple。你可以使用這樣的東西。

class ScoreFact(object): 
    def __init__(self, year, player, team, score): 
     self.year= year 
     self.player= player 
     self.team= team 
     self.score= score 
     years[self.year].append(self) 
     players[self.player].append(self) 
     teams[self.team].append(self) 

現在您可以找到給定尺寸值中的所有項目。這是一個附加到維度值的簡單列表。

years['2001'] are all scores for the given year. 

players['SEA'] are all scores for the given player. 

等,您可以簡單地使用sum()他們加起來。多維查詢就像這樣。

[ x for x in players['SEA'] if x.year == '2001' ] 
+0

我這個喜歡了不少,但是不是內存密集?我想你只能存儲三個引用而不是三個值的副本,但仍然... – Wells 2009-11-09 20:12:16

+0

這是標準的星型模式設計。你可以在SQL中實現它,或者擱置或者純粹的內存。它只需要比單純的事實清單更多的存儲空間。具體來說,它需要額外的字典 - 這只是對原始事實集合中的對象的引用。 – 2009-11-09 20:57:01

4

把你的數據到SQLite和利用其關係引擎做的工作。您可以創建內存數據庫,甚至無需觸摸磁盤。

1

語法stats[year=2001, idx=3]無效Python和沒有辦法你可以把它與方括號和「關鍵字參數」工作;您需要調用函數或方法才能接受關鍵字參數。

所以,說我們使它成爲一個功能,被稱爲像wells(stats, year=2001, idx=3)。我認爲idx參數是強制性的(這個調用非常奇特,但是你沒有指出什麼可能意味着省略idx),並且只有一年,playerid和teamid必須在那裏。

根據您當前的數據結構,井已經可以實現:

def wells(stats, year=None, playerid=None, teamid=None, idx=None): 
    if idx is None: raise ValueError('idx must be specified') 
    specifiers = [(i, x) for x in enumerate((year, playerid, teamid)) if x is not None] 
    if len(specifiers) != 2: 
    raise ValueError('Exactly one of year, playerid, teamid, must be given') 
    ikey, keyv = specifiers[0] 
    return sum(v[idx] for k, v in stats.iteritems() if k[ikey]==keyv) 
當然

,這是在stats大小O(N) - 它必須檢查它的每一個條目。請以此簡單實施作爲基準來衡量正確性和性能。另一種解決方案(使用速度更快,但需要大量時間準備)是在stats的一側放入三個清單(每年一個,playerid,teamid),每個條目表示(或複製,但我認爲表示通過全鍵可能就足夠了)與ikey/keyv對相匹配的所有統計條目。但目前還不清楚這個實現是否可能爲時過早,所以請先嚐試一下頭腦簡單的想法!)

0
def getSum(d, year, idx): 
    sum = 0 
    for key in d.keys(): 
     if key[0] == year: 
      sum += d[key][idx] 
    return sum 

這應該讓你開始。我已經在這個代碼的假設,認爲只有一年將被要求提供,但它應該是很容易爲你處理此檢查其它參數,以及

乾杯