Skip to content

Commit 233c66d

Browse files
committed
Merge pull request #26 from tacaswell/enh_by_key
ENH: add by_key
2 parents 78f477d + 714b346 commit 233c66d

File tree

3 files changed

+72
-13
lines changed

3 files changed

+72
-13
lines changed

cycler.py

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ def _from_iter(cls, label, itr):
216216
def __getitem__(self, key):
217217
# TODO : maybe add numpy style fancy slicing
218218
if isinstance(key, slice):
219-
trans = self._transpose()
219+
trans = self.by_key()
220220
return reduce(add, (_cycler(k, v[key])
221221
for k, v in six.iteritems(trans)))
222222
else:
@@ -255,7 +255,7 @@ def __mul__(self, other):
255255
if isinstance(other, Cycler):
256256
return Cycler(self, other, product)
257257
elif isinstance(other, int):
258-
trans = self._transpose()
258+
trans = self.by_key()
259259
return reduce(add, (_cycler(k, v*other)
260260
for k, v in six.iteritems(trans)))
261261
else:
@@ -346,17 +346,21 @@ def _repr_html_(self):
346346
output += "</table>"
347347
return output
348348

349-
def _transpose(self):
350-
"""
351-
Internal helper function which iterates through the
352-
styles and returns a dict of lists instead of a list of
353-
dicts. This is needed for multiplying by integers and
354-
for __getitem__
349+
def by_key(self):
350+
"""Values by key
351+
352+
This returns the transposed values of the cycler. Iterating
353+
over a `Cycler` yields dicts with a single value for each key,
354+
this method returns a `dict` of `list` which are the values
355+
for the given key.
356+
357+
The returned value can be used to create an equivalent `Cycler`
358+
using only `+`.
355359
356360
Returns
357361
-------
358-
trans : dict
359-
dict of lists for the styles
362+
transpose : dict
363+
dict of lists of the values for each key.
360364
"""
361365

362366
# TODO : sort out if this is a bottle neck, if there is a better way
@@ -371,6 +375,9 @@ def _transpose(self):
371375
out[k].append(d[k])
372376
return out
373377

378+
# for back compatibility
379+
_transpose = by_key
380+
374381
def simplify(self):
375382
"""Simplify the Cycler
376383
@@ -386,7 +393,7 @@ def simplify(self):
386393
# ((a + b) + (c + d))
387394
# I would believe that there is some performance implications
388395

389-
trans = self._transpose()
396+
trans = self.by_key()
390397
return reduce(add, (_cycler(k, v) for k, v in six.iteritems(trans)))
391398

392399
def concat(self, other):
@@ -453,8 +460,8 @@ def concat(left, right):
453460

454461
raise ValueError(msg)
455462

456-
_l = left._transpose()
457-
_r = right._transpose()
463+
_l = left.by_key()
464+
_r = right.by_key()
458465
return reduce(add, (_cycler(k, _l[k] + _r[k]) for k in left.keys))
459466

460467

doc/source/index.rst

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,26 @@ Cycles can be sliced with :obj:`slice` objects
210210
211211
to return a sub-set of the cycle as a new `Cycler`.
212212

213+
Inspecting the `Cycler`
214+
-----------------------
215+
216+
To inspect the values of the transposed `Cycler` use
217+
the `Cycler.by_key` method:
218+
219+
.. ipython:: python
220+
221+
c_m.by_key()
222+
223+
This `dict` can be mutated and used to create a new `Cycler` with
224+
the updated values
225+
226+
.. ipython:: python
227+
228+
bk = c_m.by_key()
229+
bk['color'] = ['green'] * len(c_m)
230+
cycler(**bk)
231+
232+
213233
Examples
214234
--------
215235

test_cycler.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
assert_raises, assert_true)
88
from itertools import product, cycle, chain
99
from operator import add, iadd, mul, imul
10+
from collections import defaultdict
1011

1112

1213
def _cycler_helper(c, length, keys, values):
@@ -95,6 +96,8 @@ def test_failures():
9596
assert_raises(ValueError, iadd, c1, c2)
9697
assert_raises(ValueError, mul, c1, c2)
9798
assert_raises(ValueError, imul, c1, c2)
99+
assert_raises(TypeError, iadd, c2, 'aardvark')
100+
assert_raises(TypeError, imul, c2, 'aardvark')
98101

99102
c3 = cycler(ec=c1)
100103

@@ -265,6 +268,8 @@ def test_eq():
265268
yield _eq_test_helper, a, c, False
266269
d = cycler(c='ymk')
267270
yield _eq_test_helper, b, d, False
271+
e = cycler(c='orange')
272+
yield _eq_test_helper, b, e, False
268273

269274

270275
def test_cycler_exceptions():
@@ -296,3 +301,30 @@ def test_concat_fail():
296301
b = cycler('b', range(3))
297302
assert_raises(ValueError, concat, a, b)
298303
assert_raises(ValueError, a.concat, b)
304+
305+
306+
def _by_key_helper(cy):
307+
res = cy.by_key()
308+
target = defaultdict(list)
309+
for sty in cy:
310+
for k, v in sty.items():
311+
target[k].append(v)
312+
313+
assert_equal(res, target)
314+
315+
316+
def test_by_key_add():
317+
input_dict = dict(c=list('rgb'), lw=[1, 2, 3])
318+
cy = cycler(c=input_dict['c']) + cycler(lw=input_dict['lw'])
319+
res = cy.by_key()
320+
assert_equal(res, input_dict)
321+
yield _by_key_helper, cy
322+
323+
324+
def test_by_key_mul():
325+
input_dict = dict(c=list('rg'), lw=[1, 2, 3])
326+
cy = cycler(c=input_dict['c']) * cycler(lw=input_dict['lw'])
327+
res = cy.by_key()
328+
assert_equal(input_dict['lw'] * len(input_dict['c']),
329+
res['lw'])
330+
yield _by_key_helper, cy

0 commit comments

Comments
 (0)