@@ -77,6 +77,41 @@ def _process_keys(left, right):
77
77
return l_key | r_key
78
78
79
79
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
+
80
115
class Cycler (object ):
81
116
"""
82
117
Composable cycles
@@ -183,16 +218,6 @@ def change_key(self, old, new):
183
218
# iteration.
184
219
self ._left = [{new : entry [old ]} for entry in self ._left ]
185
220
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
-
196
221
@classmethod
197
222
def _from_iter (cls , label , itr ):
198
223
"""
@@ -228,9 +253,14 @@ def __getitem__(self, key):
228
253
229
254
def __iter__ (self ):
230
255
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
234
264
235
265
def __add__ (self , other ):
236
266
"""
@@ -403,73 +433,7 @@ def simplify(self):
403
433
trans = self .by_key ()
404
434
return reduce (add , (_cycler (k , v ) for k , v in trans .items ()))
405
435
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
473
437
474
438
475
439
def cycler (* args , ** kwargs ):
0 commit comments