如何以有意义的方式读取字典键?

时间:2011-02-16 02:18:20

标签: python dictionary glob

我有大约一千个以半合理方式命名的文件,如下所示:

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列数字,我需要读入字典:波长,通量。阅读部分对我来说很容易,困难的是我需要加载这些词典,以便它们存储如下信息:

波长['aaa.ba.ca.01'](这是一个文件的波长)

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

波长['aaa.ba'](也包括所有“子文件”的所有波长 - 再次按顺序排列)。

等等。文件名表现良好(各部分以句点分隔,分组层次总是相同的方向等)但文件可以在4个部分之间,或8个部分之间。

我的问题:是否有一些合理的方法让python glob获得文件的名称,通过解析字符串或其他一些魔法将数据导入这些词典?我撞到了一堵砖墙。

3 个答案:

答案 0 :(得分: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]

至于在字典中获取数据,只需使用glob或os.listdir迭代所有文件,并使用文件名作为键将所需内容作为列表读入MultiDict项目。

答案 1 :(得分: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'。

如果你愿意,我会将每个“级别”嵌套到它自己的字典中。这样你就可以快速映射到波长等等。

答案 2 :(得分: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)