@@ -45,6 +45,7 @@ def flatten( iterables ):
4545 return chain .from_iterable ( iterables )
4646
4747
48+ # noinspection PyPep8Naming
4849class concat ( object ):
4950 """
5051 A literal iterable that lets you combine sequence literals (lists, set) with generators or list
@@ -66,6 +67,9 @@ class concat( object ):
6667 >>> list( concat( 1, xrange( 2, 4 ), 4 ) )
6768 [1, 2, 3, 4]
6869
70+ It only does so one level deep. If you need to recursively flatten a data structure,
71+ check out crush().
72+
6973 If you want to prevent that flattening for an iterable argument, wrap it in concat():
7074
7175 >>> list( concat( 1, concat( xrange( 2, 4 ) ), 4 ) )
@@ -75,13 +79,13 @@ class concat( object ):
7579
7680 >>> list( concat() ) # empty concat
7781 []
78- >>> list( concat( 1 ) ) # non-iterable singleton
82+ >>> list( concat( 1 ) ) # non-iterable
7983 [1]
80- >>> list( concat( concat() ) ) # empty, iterable singleton
84+ >>> list( concat( concat() ) ) # empty iterable
8185 []
82- >>> list( concat( concat( 1 ) ) ) # singleton singleton
86+ >>> list( concat( concat( 1 ) ) ) # singleton iterable
8387 [1]
84- >>> list( concat( 1, concat( 2 ), 3 ) )
88+ >>> list( concat( 1, concat( 2 ), 3 ) ) # flattened iterable
8589 [1, 2, 3]
8690 >>> list( concat( 1, [2], 3 ) ) # flattened iterable
8791 [1, 2, 3]
@@ -118,3 +122,48 @@ def expand( x ):
118122 return i
119123
120124 return flatten ( imap ( expand , self .args ) )
125+
126+
127+ # noinspection PyPep8Naming
128+ class crush ( object ):
129+ """
130+ >>> list(crush([]))
131+ []
132+ >>> list(crush([[]]))
133+ []
134+ >>> list(crush([1]))
135+ [1]
136+ >>> list(crush([[1]]))
137+ [1]
138+ >>> list(crush([[[]]]))
139+ []
140+ >>> list(crush([1,(),['two'],([3, 4],),{5}]))
141+ [1, 'two', 3, 4, 5]
142+
143+ >>> list(crush(1))
144+ Traceback (most recent call last):
145+ ...
146+ TypeError: 'int' object is not iterable
147+
148+ >>> list(crush('123'))
149+ ['1', '2', '3']
150+
151+ The above is a bit of an anomaly since strings occurring inside iterables are not broken up:
152+
153+ >>> list(crush(['123']))
154+ ['123']
155+ """
156+
157+ def __init__ ( self , iterables ):
158+ super ( crush , self ).__init__ ( )
159+ self .iterables = iterables
160+
161+ def __iter__ ( self ):
162+ def expand ( x ):
163+ try :
164+ # Using __iter__() instead of iter() prevents breaking up of strings
165+ return crush ( x .__iter__ ( ) )
166+ except AttributeError :
167+ return x ,
168+
169+ return flatten ( imap ( expand , self .iterables ) )
0 commit comments