2013-08-28 70 views
3

我正在寻找一个数据结构来表示一些遗传数据。该数据可以表示为大小为n的列表,其中每个条目还具有在0和1之间的实数的“遗传位置”。为了使命名清晰,我将称为列表id中的位置,并且遗传位置gpos。我实施这种方式是作为一类与自定义索引的数据结构

class Coords(object): 

    def __init__(self, *args, **kwargs): 
     self.f = list(*args, **kwargs) 
     self.r = dict() 
     for i,e in enumerate(self.f): 
      self.r[e] = i 

    def __setitem__(self,x,y): 
     self.f.__setitem__(x,y) 
     self.r.__setitem__(y,x) 

    def __getitem__(self,x): 
     return self.f.__getitem__(x) 

    def __len__(self): 
     return self.f.__len__() 

现在,我有两个问题与此。第一个是self.r的indeces是浮动的,这显然是一个坏主意。我正在考虑将它们转换为字符串(具有固定的数字位数),但是有更好的主意吗?另一个问题我已经是我想要实现通过gpos访问的条目,所以如果我举个例子,想gpos 0.2和0.4之间的访问一切,我希望能够做到这一点使用

import numpy as np 
Coords(np.arange(1,0,-.1)) 
c.r[0.2:0.4] 

有没有简单的方法来定义?我正在考虑使用二进制搜索找到正确的id的起始和结束位置,然后使用这些ID访问self.f,但有没有一种方法可以实现上述语法?

回答

5

当您用切片索引对象时,Python会用您提供的输入创建一个slice对象。例如,如果您执行c[0.2:0.4],则传递给c.__getitem__的参数将为slice(0.2, 0.4)。所以,你可以有这样的事情代码在你__getitem__方法:

def __getitem__(self, x): 
    if isinstance(x, slice): 
     start = x.start 
     stop = x.stop 
     step = x.step 
     # Do whatever you want to do to define your return 
    ... 

如果你想在Coords对象上不能使用这个花哨的索引,但在self.r字典,我认为最简单的是创建一个FancyIndexDictdict的子类,修改其__getitem__方法,然后使self.rFancyIndexDict,而不是dict

+2

这很酷,我没有不知道切片符号接受了非int参数! – lmjohns3

+0

直到我试着写这个答案时,我都没有... – Jaime

+1

其实我只是尝试过其他数据类型,它似乎基本上任何表达式都可以工作,甚至疯狂像'fancy_obj ['a':('b',8 )]' – lmjohns3

3

如果您知道您的gpos值将(或可以)始终按排序顺序存储,那么我肯定会推荐使用二进制搜索来执行此任务。您可以利用数组语法和numpy的内置实现与searchsorted

>>> gpos_vals = np.linspace(0, 1, 11) 
>>> gpos_vals 
array([ 0. , 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1. ]) 
>>> lo, hi = gpos_vals.searchsorted([0.22, 0.52]) 
>>> lo, hi 
(3, 6) 
>>> gpos_vals[lo:hi] 
array([ 0.3, 0.4, 0.5]) 

我觉得这很好地避免了您指出了使用的float字典键,这可能是有问题的有关问题。

您还可以结合这个答案与海梅的和做的一类,以查找自定义__getitem__内切片,然后通过切片参数searchsorted在我的代码片段:

class GeneticPositions(object): 
    def __init__(self, gpos_values): 
     self.gpos_values = np.asarray(gpos_values) 

    def __getitem__(self, x): 
     if isinstance(x, slice): 
      lo, hi = self.gpos_values.searchsorted(
       [x.start or 0, x.stop or 1]) 
      return self.gpos_values[lo:hi] 
     return self.gpos_values[x] 
+0

不错!在调用'np.searchsorted'之前,你实际上必须在'x.start'和'x.stop'的值中检查'None':一部分'[:0.3]'将'.start'设置为'None '(和往常一样''和'.stop'到'0.3')。 – Jaime

+0

@Jaime很好抓! – lmjohns3