def addEntry(self,commandStrings, command): #check commandStrings if commandStrings == None or type(commandStrings) != list or len(commandStrings) < 0: raise triesException("need string token to find a value, no token found") #search a similar commandString tries_tmp = self.levelOneTries for i in range(0,len(commandStrings)): tmp = tries_tmp.search(commandStrings[i]) if tmp != None and tmp.value != None: if isinstance(tmp.value,tries) : tries_tmp = tmp.value continue #elif isinstance(tmp,commandShell) : #on ne sait pas encore ce qu'on va stocker dans le multitries # raise triesException("a similar command chain already exists") else: existingPath = "" for k in range(0,i): existingPath += commandStrings[k]+" " raise triesException("can't insert a command here, another command already exists <"+existingPath+">"+" vs <"+str(commandStrings)+">") break #insert the new command string for j in range(i,len(commandStrings)-1): tries_tmp = tries_tmp.insert(commandStrings[j],tries("")).value else: j = len(commandStrings)-2 tries_tmp.insert(commandStrings[j+1],command)
def searchEntryFromMultiplePrefix(self, commandStrings, returnTriesValue=False): #check commandStrings if commandStrings == None or type(commandStrings) != list or len( commandStrings) < 0: raise triesException( "need string token to find a value, no token found") #search string tries_tmp = self.levelOneTries for i in range(0, len(commandStrings)): tmp = tries_tmp.searchUniqueFromPrefix(commandStrings[i]) if tmp != None and tmp.value != None: if isinstance(tmp.value, tries): tries_tmp = tmp.value continue else: return tmp, commandStrings[(i + 1):] else: raise triesException("unknown chain in level " + str(i) + " <" + commandStrings[i] + ">") if not returnTriesValue: raise triesException("uncomplete command") return tries_tmp, []
def searchNode(self,prefix,exactResult,partialResult = noneFunc, noMatchChild = noneFunc, falseResult = noneFunc): #must be a valid string if prefix == None or type(prefix) != str or len(prefix) == 0: raise triesException("the searched key must be a string with a length bigger than zero") currentNode = self currentPrefix = prefix totalCount = 0 while True: #count the common char with this node key count = charInCommons(currentNode.key, currentPrefix) totalCount += count #the current key node is completly used if count == len(currentNode.key): #valide string and end node if len(currentPrefix) == count: return exactResult(currentNode,prefix) # bear = bear #perfect concordance, prefix is equal to a prefix in the tree #else count < len(self.key): currentPrefix = currentPrefix[len(currentNode.key):] for child in currentNode.childs: if child.canPropagate(currentPrefix): currentNode = child break else: return noMatchChild(currentNode,prefix,totalCount) # bearor > bear else: #count < len(self.key) if len(currentPrefix) == count: return partialResult(currentNode,prefix,count,totalCount) # be < bear #partial match, prefix is a part of a prefix in the tree return falseResult(currentNode,prefix,count,totalCount) # bee != bear
def exact(Node, prefix): if Node.value != None: return Node #if the current node has a None value, it's an intermediate node with at most two children raise triesException("the prefix <" + str(prefix) + "> corresponds to multiple node")
def insert(self,key, value): if value == None: raise triesException("the inserted value can't be none") def exact(Node,key): if Node.value != None : #is it a value node? raise triesException("the inserted key already exists") return Node def partial(Node,key,count,totalCount): tempTries = tries(Node.key[count:], Node, Node.value) tempTries.childs = Node.childs for child in tempTries.childs: child.parent = tempTries tempTries.value = Node.value Node.key = Node.key[:count] #le noeud courant recupere la nouvelle valeur #Node.value = value Node.childs = [tempTries] return Node def noMatchChild(Node,key,totalCount): newNode = tries(key[totalCount:],Node) Node.childs.append(newNode) return newNode def false(Node,key,count,totalCount): tempTries = tries(Node.key[count:], Node, Node.value) tempTries.childs = Node.childs for child in tempTries.childs: child.parent = tempTries tempTries.value = Node.value Node.key = Node.key[:count] #creation du nouveau noeud newTries = tries(key[totalCount:], Node) #mise a jour du noeud courant, non value node, devient un noeud pivot Node.childs = [tempTries,newTries] Node.value = None return newTries Node = self.searchNode(key,exact,partial,noMatchChild,false) Node.value = value return Node
def insert(self, key, value): if value == None: raise triesException("the inserted value can't be none") def exact(Node, key): if Node.value != None: #is it a value node? raise triesException("the inserted key already exists") return Node def partial(Node, key, count, totalCount): tempTries = tries(Node.key[count:], Node, Node.value) tempTries.childs = Node.childs for child in tempTries.childs: child.parent = tempTries tempTries.value = Node.value Node.key = Node.key[:count] #le noeud courant recupere la nouvelle valeur #Node.value = value Node.childs = [tempTries] return Node def noMatchChild(Node, key, totalCount): newNode = tries(key[totalCount:], Node) Node.childs.append(newNode) return newNode def false(Node, key, count, totalCount): tempTries = tries(Node.key[count:], Node, Node.value) tempTries.childs = Node.childs for child in tempTries.childs: child.parent = tempTries tempTries.value = Node.value Node.key = Node.key[:count] #creation du nouveau noeud newTries = tries(key[totalCount:], Node) #mise a jour du noeud courant, non value node, devient un noeud pivot Node.childs = [tempTries, newTries] Node.value = None return newTries Node = self.searchNode(key, exact, partial, noMatchChild, false) Node.value = value return Node
def update(self, key, newValue): def exact(Node, prefix): return Node Node = self.searchNode(key, exact) if Node != None and Node.value != None: Node.value = newValue return Node raise triesException("key not found")
def removeEntry(self, commandStrings): #check commandStrings if commandStrings == None or type(commandStrings) != list or len( commandStrings) < 0: raise triesException( "need string token to find a value, no token found") #creer un tableau avec tous les tries composant la commande tries_tmp = self.levelOneTries tries_table = [self.levelOneTries] for i in range(0, len(commandStrings)): tmp = tries_tmp.searchUniqueFromPrefix(commandStrings[i]) if tmp != None and tmp.value != None: if isinstance(tmp.value, tries): tries_tmp = tmp.value tries_table.append(tries_tmp) continue else: if i == len(commandStrings) - 1: break raise triesException("the command string doesn't exist") else: raise triesException("unknown chain in level " + str(i) + " <" + commandStrings[i] + ">") #on retire les elements du bas vers le haut for i in range(0, len(tries_table)): indice = len(tries_table) - 1 - i #le tries ne contient qu'un element? if tries_table[indice].countValue() == 1: if indice == 0: tries_table[indice].remove(commandStrings[indice]) else: continue #on propage la suppression au noeud parent else: #supprimer la cle du tries tries_table[indice].remove(commandStrings[indice]) break
def update(self, key, newValue): def exact(Node,prefix): return Node Node = self.searchNode(key,exact) if Node != None and Node.value != None: Node.value = newValue return Node raise triesException("key not found")
def removeEntry(self,commandStrings): #check commandStrings if commandStrings == None or type(commandStrings) != list or len(commandStrings) < 0: raise triesException("need string token to find a value, no token found") #creer un tableau avec tous les tries composant la commande tries_tmp = self.levelOneTries tries_table = [self.levelOneTries] for i in range(0,len(commandStrings)): tmp = tries_tmp.searchUniqueFromPrefix(commandStrings[i]) if tmp != None and tmp.value != None: if isinstance(tmp.value,tries) : tries_tmp = tmp.value tries_table.append(tries_tmp) continue else: if i == len(commandStrings)-1: break raise triesException("the command string doesn't exist") else: raise triesException("unknown chain in level "+str(i)+" <"+commandStrings[i]+">") #on retire les elements du bas vers le haut for i in range(0,len(tries_table)): indice = len(tries_table)-1-i #le tries ne contient qu'un element? if tries_table[indice].countValue() == 1: if indice == 0: tries_table[indice].remove(commandStrings[indice]) else: continue #on propage la suppression au noeud parent else: #supprimer la cle du tries tries_table[indice].remove(commandStrings[indice]) break
def searchEntryFromMultiplePrefix(self,commandStrings,returnTriesValue = False): #check commandStrings if commandStrings == None or type(commandStrings) != list or len(commandStrings) < 0: raise triesException("need string token to find a value, no token found") #search string tries_tmp = self.levelOneTries for i in range(0,len(commandStrings)): tmp = tries_tmp.searchUniqueFromPrefix(commandStrings[i]) if tmp != None and tmp.value != None: if isinstance(tmp.value,tries) : tries_tmp = tmp.value continue else: return tmp,commandStrings[(i+1):] else: raise triesException("unknown chain in level "+str(i)+" <"+commandStrings[i]+">") if not returnTriesValue: raise triesException("uncomplete command") return tries_tmp,[]
def addEntry(self, commandStrings, command): #check commandStrings if commandStrings == None or type(commandStrings) != list or len( commandStrings) < 0: raise triesException( "need string token to find a value, no token found") #search a similar commandString tries_tmp = self.levelOneTries for i in range(0, len(commandStrings)): tmp = tries_tmp.search(commandStrings[i]) if tmp != None and tmp.value != None: if isinstance(tmp.value, tries): tries_tmp = tmp.value continue #elif isinstance(tmp,commandShell) : #on ne sait pas encore ce qu'on va stocker dans le multitries # raise triesException("a similar command chain already exists") else: existingPath = "" for k in range(0, i): existingPath += commandStrings[k] + " " raise triesException( "can't insert a command here, another command already exists <" + existingPath + ">" + " vs <" + str(commandStrings) + ">") break #insert the new command string for j in range(i, len(commandStrings) - 1): tries_tmp = tries_tmp.insert(commandStrings[j], tries("")).value else: j = len(commandStrings) - 2 tries_tmp.insert(commandStrings[j + 1], command)
def searchNode(self, prefix, exactResult, partialResult=noneFunc, noMatchChild=noneFunc, falseResult=noneFunc): #must be a valid string if prefix == None or type(prefix) != str or len(prefix) == 0: raise triesException( "the searched key must be a string with a length bigger than zero" ) currentNode = self currentPrefix = prefix totalCount = 0 while True: #count the common char with this node key count = charInCommons(currentNode.key, currentPrefix) totalCount += count #the current key node is completly used if count == len(currentNode.key): #valide string and end node if len(currentPrefix) == count: return exactResult( currentNode, prefix ) # bear = bear #perfect concordance, prefix is equal to a prefix in the tree #else count < len(self.key): currentPrefix = currentPrefix[len(currentNode.key):] for child in currentNode.childs: if child.canPropagate(currentPrefix): currentNode = child break else: return noMatchChild(currentNode, prefix, totalCount) # bearor > bear else: #count < len(self.key) if len(currentPrefix) == count: return partialResult( currentNode, prefix, count, totalCount ) # be < bear #partial match, prefix is a part of a prefix in the tree return falseResult(currentNode, prefix, count, totalCount) # bee != bear
def remove(self, key): def exact(Node,prefix): return Node Node = self.searchNode(key,exact) if Node != None and Node.value != None: if Node.parent == None: if len(Node.key) > 0: for child in Node.childs: child.key = Node.key + child.key Node.key = "" Node.value = None elif len(Node.childs) == 1: Node.childs[0].key = Node.key + Node.childs[0].key Node.parent.childs.remove(Node) Node.parent.childs.append(Node.childs[0]) Node.childs[0].parent = Node.parent del Node elif len(Node.childs) > 1: Node.value = None else: #len(Node.childs) == 0 Node.parent.childs.remove(Node) #cas limite, a t'on un parent None Node desequilibre? parent = Node.parent if parent.value == None and len(parent.childs) == 1: parent.childs[0].key = parent.key + parent.childs[0].key #on est a la racine? if parent.parent == None: parent.key = "" else: parent.parent.childs.remove(parent) parent.parent.childs.append(parent.childs[0]) parent.childs[0].parent = parent.parent del parent del Node return raise triesException("key not found")
def remove(self, key): def exact(Node, prefix): return Node Node = self.searchNode(key, exact) if Node != None and Node.value != None: if Node.parent == None: if len(Node.key) > 0: for child in Node.childs: child.key = Node.key + child.key Node.key = "" Node.value = None elif len(Node.childs) == 1: Node.childs[0].key = Node.key + Node.childs[0].key Node.parent.childs.remove(Node) Node.parent.childs.append(Node.childs[0]) Node.childs[0].parent = Node.parent del Node elif len(Node.childs) > 1: Node.value = None else: #len(Node.childs) == 0 Node.parent.childs.remove(Node) #cas limite, a t'on un parent None Node desequilibre? parent = Node.parent if parent.value == None and len(parent.childs) == 1: parent.childs[0].key = parent.key + parent.childs[0].key #on est a la racine? if parent.parent == None: parent.key = "" else: parent.parent.childs.remove(parent) parent.parent.childs.append(parent.childs[0]) parent.childs[0].parent = parent.parent del parent del Node return raise triesException("key not found")
def exact(Node,key): if Node.value != None : #is it a value node? raise triesException("the inserted key already exists") return Node
def exact(Node, key): if Node.value != None: #is it a value node? raise triesException("the inserted key already exists") return Node
def exact(Node,prefix): if Node.value != None: return Node #if the current node has a None value, it's an intermediate node with at most two children raise triesException("the prefix <"+str(prefix)+"> corresponds to multiple node")