diff options
Diffstat (limited to 'intern/python/modules/mcf/utils/collapse.py')
-rw-r--r-- | intern/python/modules/mcf/utils/collapse.py | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/intern/python/modules/mcf/utils/collapse.py b/intern/python/modules/mcf/utils/collapse.py new file mode 100644 index 00000000000..25da50c2adb --- /dev/null +++ b/intern/python/modules/mcf/utils/collapse.py @@ -0,0 +1,169 @@ +''' +Destructive Functions for "collapsing" Sequences into single levels + +>>> from mcf.utils import collapse + +>>> collapse.test([[[1],[2,3]],[[]],[4],5,[6]]) + +[1, 2, 3, 4, 5, 6] # note that is the same root list + +>>> collapse.collapse2([[[1],[2,3]],[[]],(4,()),(5,),[6]]) + +[1, 2, 3, 4, 5, 6] # note is the same root list +''' +import copy, types, sys +from types import ListType, TupleType # this now only supports the obsolete stuff... + +def hyperCollapse( inlist, allowedmap, type=type, list=list, itype=types.InstanceType, maxint= sys.maxint): + ''' + Destructively flatten a mixed hierarchy to a single level. + Non-recursive, many speedups and obfuscations by Tim Peters :) + ''' + try: + # for every possible index + for ind in xrange( maxint): + # while that index currently holds a list + expandable = 1 + while expandable: + expandable = 0 + if allowedmap.has_key( type(inlist[ind]) ): + # expand that list into the index (and subsequent indicies) + inlist[ind:ind+1] = list( inlist[ind]) + expandable = 1 + + # alternately you could iterate through checking for isinstance on all possible + # classes, but that would be very slow + elif type( inlist[ind] ) is itype and allowedmap.has_key( inlist[ind].__class__ ): + # here figure out some way to generically expand that doesn't risk + # infinite loops... + templist = [] + for x in inlist[ind]: + templist.append( x) + inlist[ind:ind+1] = templist + expandable = 1 + except IndexError: + pass + return inlist + + +def collapse(inlist, type=type, ltype=types.ListType, maxint= sys.maxint): + ''' + Destructively flatten a list hierarchy to a single level. + Non-recursive, and (as far as I can see, doesn't have any + glaring loopholes). + Further speedups and obfuscations by Tim Peters :) + ''' + try: + # for every possible index + for ind in xrange( maxint): + # while that index currently holds a list + while type(inlist[ind]) is ltype: + # expand that list into the index (and subsequent indicies) + inlist[ind:ind+1] = inlist[ind] + #ind = ind+1 + except IndexError: + pass + return inlist + +def collapse_safe(inlist): + ''' + As collapse, but works on a copy of the inlist + ''' + return collapse( inlist[:] ) + +def collapse2(inlist, ltype=(types.ListType, types.TupleType), type=type, maxint= sys.maxint ): + ''' + Destructively flatten a list hierarchy to a single level. + Will expand tuple children as well, but will fail if the + top level element is not a list. + Non-recursive, and (as far as I can see, doesn't have any + glaring loopholes). + ''' + ind = 0 + try: + while 1: + while type(inlist[ind]) in ltype: + try: + inlist[ind:ind+1] = inlist[ind] + except TypeError: + inlist[ind:ind+1] = list(inlist[ind]) + ind = ind+1 + except IndexError: + pass + return inlist + +def collapse2_safe(inlist): + ''' + As collapse2, but works on a copy of the inlist + ''' + return collapse( list(inlist) ) + +def old_buggy_collapse(inlist): + '''Always return a one-level list of all the non-list elements in listin, + rewritten to be non-recursive 96-12-28 Note that the new versions work + on the original list, not a copy of the original.''' + if type(inlist)==TupleType: + inlist = list(inlist) + elif type(inlist)!=ListType: + return [inlist] + x = 0 + while 1: + try: + y = inlist[x] + if type(y) == ListType: + ylen = len(y) + if ylen == 1: + inlist[x] = y[0] + if type(inlist[x]) == ListType: + x = x - 1 # need to collapse that list... + elif ylen == 0: + del(inlist[x]) + x = x-1 # list has been shortened + else: + inlist[x:x+1]=y + x = x+1 + except IndexError: + break + return inlist + + +def old_buggy_collapse2(inlist): + '''As collapse, but also collapse tuples, rewritten 96-12-28 to be non-recursive''' + if type(inlist)==TupleType: + inlist = list(inlist) + elif type(inlist)!=ListType: + return [inlist] + x = 0 + while 1: + try: + y = inlist[x] + if type(y) in [ListType, TupleType]: + ylen = len(y) + if ylen == 1: + inlist[x] = y[0] + if type(inlist[x]) in [ListType,TupleType]: + x = x-1 #(to deal with that element) + elif ylen == 0: + del(inlist[x]) + x = x-1 # list has been shortened, will raise exception with tuples... + else: + inlist[x:x+1]=list(y) + x = x+1 + except IndexError: + break + return inlist + + +def oldest_buggy_collapse(listin): + 'Always return a one-level list of all the non-list elements in listin' + if type(listin) == ListType: + return reduce(lambda x,y: x+y, map(collapse, listin), []) + else: return [listin] + +def oldest_buggy_collapse2(seqin): + + if type(seqin) in [ListType, TupleType]: + return reduce(lambda x,y: x+y, map(collapse2, seqin), []) + else: + return [seqin] + |