2011-02-16 64 views
1

我有大約一千了在一個半明智的方式類似如下命名文件:如何以有意義的方式閱讀字典鍵?

aaa.ba.ca.01 
aaa.ba.ca.02 
aaa.ba.ca.03 

aaa.ba.da.01 
aaa.ba.da.02 
aaa.ba.da.03 

等。假設每個文件都包含需要讀入字典的2列數字:波長,通量。閱讀部分對我來說很簡單,難的部分是我需要加載這些字典,以便他們存儲如下信息:

wavelength ['aaa.ba.ca.01'](它的波長即一個文件)

波長['aaa.ba.ca'](它是所有子文件的波長,即... ca.01,... ca.02,... ca.03 - 按順序)

波長['aaa.ba'](其中也包括所有「子文件」的所有波長)。

等。文件名行爲良好(各部分按句點分隔,分組層次始終是相同的方向等),但文件可以在4個部分之間,或8個部分長。

我的問題:是否有一些明智的方法讓python glob的文件的名稱,並通過解析字符串或一些其他魔術獲取數據到這些字典?我撞到了一堵磚牆。

回答

5

一個簡單卻不高效的方法是對Pythons字典進行子類化,以便在給定一個非完整鍵時,按字母順序連接所有匹配鍵的內容。

可能會有更高效的設計:這是一個主要缺點,因爲它會對部分密鑰請求中的所有現有字典鍵進行排序和驗證。否則,它是如此簡單實現,這是值得一試:

class MultiDict(dict): 
    def __getitem__(self, key): 
     if key in self: 
      return dict.__getitem__(self, key) 
     result = [] 
     for complete_key in sorted(self.keys()): 
      if complete_key.startswith(key): 
       result.extend(self[complete_key]) 
     return result 

#example 
a = MultiDict() 
a["a0"] = [1] 
a["a1"] = [2] 
print a["a"] 
[1, 2] 

至於字典越來越TEH數據,只是遍歷所有的文件,與水珠或os.listdir,並讀取所需的內容,作爲一個列表,使用文件名作爲關鍵字,放入MultiDict項目中。

+0

我創建了一個看起來幾乎和jsbueno完全一樣的解決方案,所以我只會投票給他。如果不是結果,可能要在`__getitem__`的最後一行之前添加:raise KeyError(key)` – 2011-02-16 03:28:55

1

你想要什麼聽起來不像字典。在很多方面,我會說這是一個與樹相媲美的數據結構。因此,而不是使用你會想使一個數據結構的字典,其中你有第一個節點:

       Root 
    'ba'    'ca'    'cd'    'fg' 
/ | \  / \   / \    | 
/ | \  / \   / \    | 
'aa' 'di' '30' '34' '45'  'ac'  'ty'  '01' 

,然後進行深度優先搜索,其中你表示葉子的數量搜索通過名字:'ba.aa'只會返回'ba' - >'aa'葉子的東西,而'ba'會返回'ba' - >'aa','ba' - >'di',並且'BA' - > '30'。

如果你願意,我會讓每個「級別」嵌套到它自己的字典中。這樣你可以快速映射到波長等。

0

如果你只有1000個文件的線性搜索來查找它們可能是好的。在我的機器上,我們花了250美元做一次查詢。然後你可以使用itertools.chain合併來自多個文件的數據。

class DataGlob(object): 

def __init__(self): 
    self.files = [] 
    self.wavedata = dict() 
    self.fluxdata = dict() 

def add(self, filename): 
    wlist = [] 
    flist = [] 
    for l in open(filename): 
     (wlen, flux) = map(float, l.split()) 
     wlist.append(wlen) 
     flist.append(flux) 
    self.wavedata[filename] = wlist 
    self.fluxdata[filename] = flist 

def find_keys(self, prefix): 
    return [f for f in self.files if f.startswith(prefix)] 

def wavelength(self,fileprefix): 
    validkeys = find_keys(prefix) 
    return itertools.chain.from_iterable(self.wavedata[k] for k in validkeys) 

def flux(self, fileprefix): 
    validkeys = self.find_keys(fileprefix) 
    return itertools.chain.from_iterable(self.fluxdata[k] for k in validkeys)