various fixes
This commit is contained in:
238
sortedlist.py
238
sortedlist.py
@@ -1,115 +1,125 @@
|
|||||||
class sortedlist:
|
class sortedlist:
|
||||||
|
|
||||||
#don't deal with this directly or you'll fuck everything up
|
#don't deal with this directly or you'll fuck everything up
|
||||||
data = []
|
data = []
|
||||||
|
|
||||||
def __init__(self, dat=[], presorted=False):
|
def __init__(self, dat=[], presorted=False):
|
||||||
if presorted:
|
if presorted:
|
||||||
self.data = dat
|
self.data = dat
|
||||||
else:
|
else:
|
||||||
self.data = sorted(dat)
|
self.data = sorted(dat)
|
||||||
|
|
||||||
def __getitem__(self, key):
|
def __getitem__(self, key):
|
||||||
return self.data[key]
|
return self.data[key]
|
||||||
|
|
||||||
def __len__(self):
|
def __len__(self):
|
||||||
return len(self.data)
|
return len(self.data)
|
||||||
|
|
||||||
def __str__(self):
|
def __repr__(self):
|
||||||
return str(self.data)
|
ret = 'sortedlist('
|
||||||
|
for i in self.data:
|
||||||
def __delitem__(self, key):
|
ret += str(i) + ', '
|
||||||
del(self.data[key])
|
return ret[:-2] + ')'
|
||||||
|
|
||||||
def __add__(self, operand):
|
def __str__(self):
|
||||||
if isinstance(operand, list):
|
return str(self.data)
|
||||||
return sortedlist(self.merge(self.data, sorted(operand)), True)
|
|
||||||
elif isinstance(operand, sortedlist):
|
def __delitem__(self, key):
|
||||||
return sortedlist(self.merge(self.data, operand.data), True)
|
del(self.data[key])
|
||||||
else:
|
|
||||||
raise TypeError('can only concatenate list or sortedlist (not "%s") to sortedlist' % type(operand).__name__)
|
def __add__(self, operand):
|
||||||
|
if isinstance(operand, list):
|
||||||
#because of sorting, addition is commutative (a + b == b + a)
|
return sortedlist(self.merge(self.data, sorted(operand)), presorted=True)
|
||||||
def __radd__(self, operand):
|
elif isinstance(operand, sortedlist):
|
||||||
return self + operand
|
return sortedlist(self.merge(self.data, operand.data), presorted=True)
|
||||||
|
else:
|
||||||
def __iadd__(self, operand):
|
return NotImplemented
|
||||||
self.data = (self + operand).data
|
|
||||||
|
#because of sorting, addition is commutative (a + b == b + a)
|
||||||
#takes two sorted lists (not sortedlists) and returns a sorted combination at O(n)
|
def __radd__(self, operand):
|
||||||
def merge(self, data1, data2):
|
return self + operand
|
||||||
ind1 = 0
|
|
||||||
ind2 = 0
|
def __iadd__(self, operand):
|
||||||
merged = []
|
self.data = (self + operand).data
|
||||||
|
return self
|
||||||
while True:
|
|
||||||
if data1[ind1] <= data2[ind2]:
|
#takes two sorted lists (not sortedlists) and returns a sorted combination at O(n)
|
||||||
merged += [data1[ind1]]
|
def merge(self, data1, data2):
|
||||||
ind1 += 1
|
ind1 = 0
|
||||||
else:
|
ind2 = 0
|
||||||
merged += [data2[ind2]]
|
merged = []
|
||||||
ind2 += 1
|
|
||||||
if ind1 >= len(data1):
|
while True:
|
||||||
return merged + data2[ind2:]
|
if data1[ind1] <= data2[ind2]:
|
||||||
break
|
merged += [data1[ind1]]
|
||||||
elif ind2 >= len(data2):
|
ind1 += 1
|
||||||
return merged + data1[ind1:]
|
else:
|
||||||
|
merged += [data2[ind2]]
|
||||||
|
ind2 += 1
|
||||||
def add(self, entry):
|
if ind1 >= len(data1):
|
||||||
self.data = self.addhelper(self.data, entry)
|
return merged + data2[ind2:]
|
||||||
|
break
|
||||||
#I couldn't figure out how to do this recursively in the add method
|
elif ind2 >= len(data2):
|
||||||
#and fuck trying to do this in a loop
|
return merged + data1[ind1:]
|
||||||
def addhelper(self, dat, entry):
|
|
||||||
if dat == []:
|
|
||||||
return [entry]
|
def add(self, entry):
|
||||||
ind = int(len(dat)/2)
|
self.data = self.addhelper(self.data, entry)
|
||||||
if entry < dat[ind]:
|
|
||||||
return self.addhelper(dat[0:ind], entry) + dat[ind:]
|
#I couldn't figure out how to do this recursively in the add method
|
||||||
else:
|
#and fuck trying to do this in a loop
|
||||||
return dat[:ind+1] + self.addhelper(dat[ind+1:], entry)
|
def addhelper(self, dat, entry):
|
||||||
|
if dat == []:
|
||||||
def isin(self, entry):
|
return [entry]
|
||||||
return self.inhelper(self.data, entry)
|
ind = int(len(dat)/2)
|
||||||
|
if entry < dat[ind]:
|
||||||
#ditto
|
return self.addhelper(dat[0:ind], entry) + dat[ind:]
|
||||||
def inhelper(self, dat, entry):
|
else:
|
||||||
if len(dat) == 0:
|
return dat[:ind+1] + self.addhelper(dat[ind+1:], entry)
|
||||||
return False
|
|
||||||
elif len(dat) == 1:
|
def isin(self, entry):
|
||||||
return entry == dat[0]
|
return self.inhelper(self.data, entry)
|
||||||
|
|
||||||
ind = int(len(dat)/2)
|
#ditto
|
||||||
if entry < dat[ind]:
|
def inhelper(self, dat, entry):
|
||||||
return self.inhelper(dat[:ind], entry)
|
if len(dat) == 0:
|
||||||
elif entry > dat[ind]:
|
return False
|
||||||
return self.inhelper(dat[ind+1:], entry)
|
elif len(dat) == 1:
|
||||||
else:
|
return entry == dat[0]
|
||||||
return True
|
|
||||||
|
ind = int(len(dat)/2)
|
||||||
#returns an arbitrary index that contains the value at O(log(n))
|
if entry < dat[ind]:
|
||||||
#returns -1 if the list doesn't contain the value
|
return self.inhelper(dat[:ind], entry)
|
||||||
def index(self, val):
|
elif entry > dat[ind]:
|
||||||
ind = self.indexhelper(self.data, val)
|
return self.inhelper(dat[ind+1:], entry)
|
||||||
if ind == len(self):
|
else:
|
||||||
ind = -1
|
return True
|
||||||
return ind
|
|
||||||
pass
|
#returns an arbitrary index that contains the value, at O(log(n))
|
||||||
|
def index(self, value):
|
||||||
#at this point I think I'm just bad at defining recursive functions
|
low = 0
|
||||||
def indexhelper(self, dat, val):
|
high = len(self)
|
||||||
ind = int(len(dat)/2)
|
mid = (low + high) / 2
|
||||||
|
while self[mid] != value:
|
||||||
if len(dat) == 0:
|
if self[mid] > value:
|
||||||
return 0
|
high = mid
|
||||||
elif dat[ind] == val:
|
else:
|
||||||
return ind
|
low = mid
|
||||||
elif dat[ind] < val:
|
mid = (high + low) / 2
|
||||||
return ind + 1 + self.indexhelper(dat[ind+1:], val)
|
if high in (low, low+1):
|
||||||
else:
|
raise ValueError('sortedlist does not contain entry')
|
||||||
return self.indexhelper(dat[:ind], val)
|
return mid
|
||||||
|
|
||||||
#TODO: add functionality for single=False
|
#removes a single instance of entry, raises exception if it doesn't exist
|
||||||
def remove(self, entry, single=True):
|
def remove(self, entry):
|
||||||
del(self[self.index(entry)])
|
del(self[self.index(entry)])
|
||||||
|
|
||||||
|
#removes every instance of entry, doesn't raise an exception if it doesn't exist
|
||||||
|
#TODO: index once, then search adacent indices
|
||||||
|
def removeall(self, entry):
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
del(self[self.index(entry)])
|
||||||
|
except ValueError:
|
||||||
|
break
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user