2015-04-14 112 views
1

我正在寻找一个python中的SQL关系表类数据结构,或者一些提示(如果没有一个存在的话)。从概念上讲,数据结构是一组对象(任何对象),支持高效查找/过滤(可能使用类似于SQL的索引)。python中的关系数据结构

例如,可以说我的对象全都具有属性ABC,我需要过滤它们,因此我定义的数据应该由它们索引。这些对象可能包含许多其他成员,这些成员不用于过滤。数据结构应支持相当于SELECT <obj> from <DATASTRUCTURE> where A=100的操作(对于BC也是如此)。也应该可以通过多个字段进行筛选(where A=100 and B='bar')。

的要求是:

  1. 应该支持大量项目(〜200K)的。这些项目必须是对象本身,而不是它们的一些扁平版本(它排除了sqlite和可能的pandas)。
  2. 插入要快,应避免的存储器再分配(这几乎排除了pandas
  3. 应该支持简单的过滤(如上面的例子),其必须比O(len(DATA))更有效率,即,避免“全表扫描” 。

这样的数据结构是否存在?


请不要使用sqlite。我需要重复转换object-> row和row-> object,这很费时间和麻烦,因为我的对象不一定是平坦的。

此外,请不要建议使用熊猫,因为重复插入的行太慢,因为它可能需要频繁的重新分配。

回答

1

只要您在(a,b,c)上没有任何重复项,您可以输入由元组(a,b,c)索引的对象,并定义过滤器方法(可能是一个生成器)返回符合条件的所有条目。

class mydict(dict): 
    def filter(self,a=None, b=None, c=None): 
     for key,obj in enumerate(self): 
      if (a and (key[0] == a)) or not a: 
       if (b and (key[1] == b)) or not b: 
        if (c and (key[2] == c)) or not c: 
         yield obj 

这是一个丑陋和非常低效的例子,但你明白了。我相信itertools中有更好的实现方法,或者其他的东西。

编辑:

我一直在想这件事。昨晚我玩弄了一些东西,想出了将这些对象存储在一个列表中,并通过所需的关键字段存储索引的字典。通过获取所有指定条件的索引的交集来检索对象。像这样:

objs = [] 
aindex = {} 
bindex = {} 
cindex = {} 

def insertobj(a,b,c,obj): 
    idx = len(objs) 
    objs.append(obj) 
    if a in aindex: 
     aindex[a].append(idx) 
    else: 
     aindex[a] = [idx] 

    if b in bindex: 
     bindex[b].append(idx) 
    else: 
     bindex[b] = [idx] 

    if c in cindex: 
     cindex[c].append(idx) 
    else : 
     cindex[c] = [idx] 

def filterobjs(a=None,b=None,c=None): 
    if a : aset = set(aindex[a]) 
    if b : bset = set(bindex[b]) 
    if c : cset = set(cindex[c]) 
    result = set(range(len(objs))) 
    if a and aset : result = result.intersection(aset) 
    if b and bset : result = result.intersection(bset) 
    if c and cset : result = result.intersection(cset) 
    for idx in result: 
     yield objs[idx] 

class testobj(object): 
    def __init__(self,a,b,c): 
     self.a = a 
     self.b = b 
     self.c = c 

    def show(self): 
     print ('a=%i\tb=%i\tc=%s'%(self.a,self.b,self.c)) 

if __name__ == '__main__': 
    for a in range(20): 
     for b in range(5): 
      for c in ['one','two','three','four']: 
       insertobj(a,b,c,testobj(a,b,c)) 

    for obj in filterobjs(a=5): 
     obj.show() 
    print() 
    for obj in filterobjs(b=3): 
     obj.show() 
    print() 
    for obj in filterobjs(a=8,c='one'): 
     obj.show() 

它应该是相当快的,尽管对象在列表中,它们可以直接通过索引访问。 “搜索”是在哈希字典上完成的。

+0

@Martijn彼得斯给出了一个很好的例子,这个问题的匹配/选择/过滤方面使用fnmatch在这里的问题[链接](http://stackoverflow.com/questions/29638382/how-to-retrieve-dicts -a-list-of-dicts-using-wildcard-key-value)。 –

+0

我喜欢这种方法 – shx2