@@ -389,6 +389,74 @@ def simplify(self):
389389 trans = self ._transpose ()
390390 return reduce (add , (_cycler (k , v ) for k , v in six .iteritems (trans )))
391391
392+ def concat (self , other ):
393+ """Concatenate this cycler and an other.
394+
395+ The keys must match exactly.
396+
397+ This returns a single Cycler which is equivalent to
398+ `itertools.chain(self, other)`
399+
400+ Examples
401+ --------
402+
403+ >>> num = cycler('a', range(3))
404+ >>> let = cycler('a', 'abc')
405+ >>> num.concat(let)
406+ cycler('a', [0, 1, 2, 'a', 'b', 'c'])
407+
408+ Parameters
409+ ----------
410+ other : `Cycler`
411+ The `Cycler` to concatenate to this one.
412+
413+ Returns
414+ -------
415+ ret : `Cycler`
416+ The concatenated `Cycler`
417+ """
418+ return concat (self , other )
419+
420+
421+ def concat (left , right ):
422+ """Concatenate two cyclers.
423+
424+ The keys must match exactly.
425+
426+ This returns a single Cycler which is equivalent to
427+ `itertools.chain(left, right)`
428+
429+ Examples
430+ --------
431+
432+ >>> num = cycler('a', range(3))
433+ >>> let = cycler('a', 'abc')
434+ >>> num.concat(let)
435+ cycler('a', [0, 1, 2, 'a', 'b', 'c'])
436+
437+ Parameters
438+ ----------
439+ left, right : `Cycler`
440+ The two `Cycler` instances to concatenate
441+
442+ Returns
443+ -------
444+ ret : `Cycler`
445+ The concatenated `Cycler`
446+ """
447+ if left .keys != right .keys :
448+ msg = '\n \t ' .join (["Keys do not match:" ,
449+ "Intersection: {both!r}" ,
450+ "Disjoint: {just_one!r}"
451+ ]).format (
452+ both = left .keys & right .keys ,
453+ just_one = left .keys ^ right .keys )
454+
455+ raise ValueError (msg )
456+
457+ _l = left ._transpose ()
458+ _r = right ._transpose ()
459+ return reduce (add , (_cycler (k , _l [k ] + _r [k ]) for k in left .keys ))
392460
393461def cycler (* args , ** kwargs ):
394462 """
0 commit comments