@@ -77,6 +77,41 @@ def _process_keys(left, right):
7777 return l_key | r_key
7878
7979
80+ def concat (left , right ):
81+ """
82+ Concatenate two cyclers, as if chained using `itertools.chain`.
83+
84+ The keys must match exactly.
85+
86+ Examples
87+ --------
88+
89+ >>> num = cycler('a', range(3))
90+ >>> let = cycler('a', 'abc')
91+ >>> num.concat(let)
92+ cycler('a', [0, 1, 2, 'a', 'b', 'c'])
93+
94+ Parameters
95+ ----------
96+ left, right : `Cycler`
97+ The two `Cycler` instances to concatenate
98+
99+ Returns
100+ -------
101+ ret : `Cycler`
102+ The concatenated `Cycler`
103+ """
104+ if left .keys != right .keys :
105+ raise ValueError ("Keys do not match:\n "
106+ "\t Intersection: {both!r}\n "
107+ "\t Disjoint: {just_one!r}" .format (
108+ both = left .keys & right .keys ,
109+ just_one = left .keys ^ right .keys ))
110+ _l = left .by_key ()
111+ _r = right .by_key ()
112+ return reduce (add , (_cycler (k , _l [k ] + _r [k ]) for k in left .keys ))
113+
114+
80115class Cycler (object ):
81116 """
82117 Composable cycles
@@ -183,16 +218,6 @@ def change_key(self, old, new):
183218 # iteration.
184219 self ._left = [{new : entry [old ]} for entry in self ._left ]
185220
186- def _compose (self ):
187- """
188- Compose the 'left' and 'right' components of this cycle
189- """
190- for a , b in self ._op (self ._left , self ._right ):
191- out = dict ()
192- out .update (a )
193- out .update (b )
194- yield out
195-
196221 @classmethod
197222 def _from_iter (cls , label , itr ):
198223 """
@@ -228,9 +253,14 @@ def __getitem__(self, key):
228253
229254 def __iter__ (self ):
230255 if self ._right is None :
231- return iter (dict (l ) for l in self ._left )
232-
233- return self ._compose ()
256+ for l in self ._left :
257+ yield dict (l )
258+ else :
259+ for a , b in self ._op (self ._left , self ._right ):
260+ out = dict ()
261+ out .update (a )
262+ out .update (b )
263+ yield out
234264
235265 def __add__ (self , other ):
236266 """
@@ -403,73 +433,7 @@ def simplify(self):
403433 trans = self .by_key ()
404434 return reduce (add , (_cycler (k , v ) for k , v in trans .items ()))
405435
406- def concat (self , other ):
407- """Concatenate this cycler and an other.
408-
409- The keys must match exactly.
410-
411- This returns a single Cycler which is equivalent to
412- `itertools.chain(self, other)`
413-
414- Examples
415- --------
416-
417- >>> num = cycler('a', range(3))
418- >>> let = cycler('a', 'abc')
419- >>> num.concat(let)
420- cycler('a', [0, 1, 2, 'a', 'b', 'c'])
421-
422- Parameters
423- ----------
424- other : `Cycler`
425- The `Cycler` to concatenate to this one.
426-
427- Returns
428- -------
429- ret : `Cycler`
430- The concatenated `Cycler`
431- """
432- return concat (self , other )
433-
434-
435- def concat (left , right ):
436- """Concatenate two cyclers.
437-
438- The keys must match exactly.
439-
440- This returns a single Cycler which is equivalent to
441- `itertools.chain(left, right)`
442-
443- Examples
444- --------
445-
446- >>> num = cycler('a', range(3))
447- >>> let = cycler('a', 'abc')
448- >>> num.concat(let)
449- cycler('a', [0, 1, 2, 'a', 'b', 'c'])
450-
451- Parameters
452- ----------
453- left, right : `Cycler`
454- The two `Cycler` instances to concatenate
455-
456- Returns
457- -------
458- ret : `Cycler`
459- The concatenated `Cycler`
460- """
461- if left .keys != right .keys :
462- msg = '\n \t ' .join (["Keys do not match:" ,
463- "Intersection: {both!r}" ,
464- "Disjoint: {just_one!r}" ]).format (
465- both = left .keys & right .keys ,
466- just_one = left .keys ^ right .keys )
467-
468- raise ValueError (msg )
469-
470- _l = left .by_key ()
471- _r = right .by_key ()
472- return reduce (add , (_cycler (k , _l [k ] + _r [k ]) for k in left .keys ))
436+ concat = concat
473437
474438
475439def cycler (* args , ** kwargs ):
0 commit comments