| | 121 | #~ Tree Iteration/Searching |
|---|
| | 122 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|
| | 123 | |
|---|
| | 124 | class TreeDict(dict): |
|---|
| | 125 | def addleaf(self, leaf): |
|---|
| | 126 | self[None] = leaf |
|---|
| | 127 | def addbranch(self, key, branch): |
|---|
| | 128 | self[key] = branch |
|---|
| | 129 | |
|---|
| | 130 | class TreeIterator(object): |
|---|
| | 131 | TreeFactory = TreeDict |
|---|
| | 132 | |
|---|
| | 133 | def __init__(self, root=()): |
|---|
| | 134 | self.SetRoot(root) |
|---|
| | 135 | |
|---|
| | 136 | def GetRoot(self, root): |
|---|
| | 137 | return self._root |
|---|
| | 138 | def SetRoot(self, root): |
|---|
| | 139 | self._root = root |
|---|
| | 140 | |
|---|
| | 141 | def isBranch(self, key, value): |
|---|
| | 142 | return bool(key) |
|---|
| | 143 | |
|---|
| | 144 | def asTree(self): |
|---|
| | 145 | resulttree = self.TreeFactory() |
|---|
| | 146 | workqueue = [(resulttree, self._GetRootAsIter())] |
|---|
| | 147 | while workqueue: |
|---|
| | 148 | tree, itemcollection = workqueue.pop() |
|---|
| | 149 | for key, item in itemcollection: |
|---|
| | 150 | if self.isBranch(key, item): |
|---|
| | 151 | try: |
|---|
| | 152 | itemtree=tree[key] |
|---|
| | 153 | except LookupError: |
|---|
| | 154 | itemtree=self.TreeFactory() |
|---|
| | 155 | tree.addbranch(key, itemtree) |
|---|
| | 156 | workqueue.append((itemtree, item)) |
|---|
| | 157 | else: |
|---|
| | 158 | tree.addleaf(item) |
|---|
| | 159 | return resulttree |
|---|
| | 160 | |
|---|
| | 161 | def iterByDepth(self, yieldkeys=False, filterDuplicates=False): |
|---|
| | 162 | iterResult = self._iter(yieldkeys, -1) |
|---|
| | 163 | if filterDuplicates: |
|---|
| | 164 | return self.iterFilterDuplicates(iterResult, yieldkeys) |
|---|
| | 165 | else: |
|---|
| | 166 | return iterResult |
|---|
| | 167 | |
|---|
| | 168 | def iterByBreadth(self, yieldkeys=False, filterDuplicates=False): |
|---|
| | 169 | iterResult = self._iter(yieldkeys, 0) |
|---|
| | 170 | if filterDuplicates: |
|---|
| | 171 | return self.iterFilterDuplicates(iterResult, yieldkeys) |
|---|
| | 172 | else: |
|---|
| | 173 | return iterResult |
|---|
| | 174 | |
|---|
| | 175 | def iterFilterDuplicates(self, iterable, resultDecorated=False): |
|---|
| | 176 | if resultDecorated: |
|---|
| | 177 | getvalue = lambda x:x[-1] |
|---|
| | 178 | else: |
|---|
| | 179 | getvalue = lambda x:x |
|---|
| | 180 | |
|---|
| | 181 | allresults = {} |
|---|
| | 182 | for item in iterable: |
|---|
| | 183 | value = getvalue(item) |
|---|
| | 184 | if value not in allresults: |
|---|
| | 185 | allresults[value]=None |
|---|
| | 186 | yield item |
|---|
| | 187 | |
|---|
| | 188 | def _GetRootAsIter(self): |
|---|
| | 189 | if callable(self._root): |
|---|
| | 190 | return self._root() |
|---|
| | 191 | else: |
|---|
| | 192 | return iter(self._root) |
|---|
| | 193 | |
|---|
| | 194 | def _iter(self, yieldkeys=False, popindex=-1): |
|---|
| | 195 | workqueue = [((), self._GetRootAsIter())] |
|---|
| | 196 | while workqueue: |
|---|
| | 197 | path, itemcollection = workqueue.pop(popindex) |
|---|
| | 198 | tempqueue = [] |
|---|
| | 199 | for key, item in itemcollection: |
|---|
| | 200 | newkey = path+(key,) |
|---|
| | 201 | if self.isBranch(key, item): |
|---|
| | 202 | tempqueue.append((newkey, item)) |
|---|
| | 203 | elif yieldkeys: |
|---|
| | 204 | yield newkey, item |
|---|
| | 205 | else: |
|---|
| | 206 | yield item |
|---|
| | 207 | if popindex<0: |
|---|
| | 208 | tempqueue.reverse() |
|---|
| | 209 | workqueue.extend(tempqueue) |
|---|
| | 210 | |
|---|
| | 211 | #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|---|