view lookup_list.py @ 160:a910141fbe5b

Automated merge with ssh://p-omega1@lgcm.iro.umontreal.ca/tlearn
author Frederic Bastien <bastienf@iro.umontreal.ca>
date Mon, 12 May 2008 16:52:00 -0400
parents ad144fa72bf5
children 4803cb76e26b
line wrap: on
line source


from copy import deepcopy

class LookupList(object):
    """
    A LookupList is a sequence whose elements can be named (and unlike
    a dictionary the order of the elements depends not on their key but
    on the order given by the user through construction) so that
    following syntactic constructions work as one would expect:
       example = LookupList(['x','y','z'],[1,2,3])
       example['x'] = [1, 2, 3] # set or change a field
       print example('z','y') # prints [3,2]
       x, y, z = example
       x = example[0]
       x = example["x"]
       print example.keys() # prints ['x','y','z']
       print example.values() # prints [[1,2,3],2,3]
       print example.items() # prints [('x',[1,2,3]),('y',2),('z',3)]
       example.append_keyval('u',0) # adds item with name 'u' and value 0
       print len(example) # number of items = 4 here
       example2 = LookupList(['v', 'w'], ['a','b'])
       print example+example2 # addition is like for lists, a concatenation of the items.
       example + example # throw an error as we can't have duplicate name.
    Note that the element names should be unique.
    """
    def __init__(self,names=[],values=[]):
        assert len(values)==len(names)
        self.__dict__['_values']=values
        self.__dict__['_name2index']={}
        self.__dict__['_names']=names
        for i in xrange(len(values)):
            assert names[i] not in self._name2index
            self._name2index[names[i]]=i

    def keys(self):
        return self._names

    def values(self):
        return self._values

    def items(self):
        """
        Return a list of (name,value) pairs of all the items in the look-up list.
        """
        return zip(self._names,self._values)
    
    def __getitem__(self,key):
        """
        The key in example[key] can either be an integer to index the fields
        or the name of the field.
        """
        if isinstance(key,int) or isinstance(key,slice) or (isinstance(key,list) and all([isinstance(i,int) for i in key])):
            return self._values[key]
        else: # if not an int, key must be a name
            # expecting key to be a valid field name
            assert isinstance(key,str)
            return self._values[self._name2index[key]]
    
    def __setitem__(self,key,value):
        if isinstance(key,int):
            self._values[key]=value
        else: # if not an int, key must be a name
            if key in self._name2index:
                self._values[self._name2index[key]]=value
            else:
                self.append_keyval(key,value)
            
    def append_keyval(self, key, value):
        assert key not in self._name2index
        self._name2index[key]=len(self)
        self._values.append(value)
        self._names.append(key)

    def append_lookuplist(self, *list):
        for l in list:
            for key in l.keys():
                self.append_keyval(key,l[key])
        del l

    def __len__(self):
        return len(self._values)

    def __repr__(self):
        return "{%s}" % ", ".join([str(k) + "=" + repr(v) for k,v in self.items()])

    def __add__(self,rhs):
        new_example = deepcopy(self)
        for item in rhs.items():
            new_example.append_keyval(item[0],item[1])
        return new_example

    def __radd__(self,lhs):
        new_example = deepcopy(lhs)
        for item in self.items():
            new_example.append_keyval(item[0],item[1])
        return new_example

    def __eq__(self, other):
        return self._values==other._values and self._name2index==other._name2index and self._names==other._names

    def __ne__(self, other):
        return not self.__eq__(other)

    def __hash__(self):
        raise NotImplementedError()

    def __call__(self,*names):
        """
        Return a list of values associated with the given names (which must all be keys of the lookup list).
        """
        return [self[name] for name in names]


if __name__ == '__main__':

    a=LookupList(['a'],[1])
    print a
    b=LookupList(['b'],[2])
    print b
    a.append_lookuplist(b)
    print a
    a.append_lookuplist(b)
    print a