0

I'm wondering what is the closest to a "SetList"; a list with all the amazing properties of both a list and a set.

For example, I'd want to index/subset it like a list, but make use of contains checking of a set, and making sure everything in it is unique.

Why not have both a set and a list occupying the same values (I know it is a terrible idea, there must be a way to contain the values once)? I figured it would be possible to implement all methods such that the list and set will always stay in sync.

I started with something like this:

class SetList():
    def __init__(self, x = None):
        if isinstance(x, list):
            self.l = []
            self.s = set()
            for y in x:
                if y not in self.s:
                    self.l.append(y)
                    self.s.add(y)
        elif isinstance(x, set):            
            self.l = list(x)
            self.s = x
        elif isinstance(x, SetList):
            self.l = SetList.l
            self.s = SetList.s
        elif x is None:
            self.l = []
            self.s = set()
        else:
            self.l = [x] 
            self.s = set(self.l)

    def append(self, a):
        if a not in self.s:
            self.l.append(a)
            self.s.add(a)

    def add(self, a):
        self.append(a)        

    def remove(self, r):
        if r in self.s:
            self.l.remove(r)
            self.s.remove(r)

    def pop(self, p = None):
        if p is not None:
            x = self.l.pop(p) 
        else:
            x = self.l.pop()
        self.s.remove(x)
        return x

    def __getitem__(self, i): 
        if isinstance(i, int):
            return self.l[i]
        else:
            return SetList(self.l[i])

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

    def __repr__(self):
        return 'SetList({})'.format(self.l)

    def __add__(self, container):
        for x in container:
            if x not in self.s:
                self.add(x)
        return self        

    def __iter__(self):
        return self.l.__iter__()

    def __item__(self, x): 
        return self.l.__item__(x)

    def __and__(self, x):
        return self.__add__(x)

    def __eq__(self, x):
        try:
            return self.l == x.l
        except AttributeError: 
            return False

Here to see the goodness in action:

sl = SetList()

for x in [1,2,3,4,1,2,3]:
    sl.add(x)

>>> sl[1:2] + [1,3] != sl[1:2] & [3,1]
True
>>> sl[1:2] + [1,3] == sl[1:2] & [1,3]
True

Though I'm wondering if there are already such implementations out there?

PascalVKooten
  • 20,643
  • 17
  • 103
  • 160

0 Answers0