1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
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]
|