Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #103530 > unrolled thread

Cycling through iterables diagonally

Started byPablo Lucena <plucena24@gmail.com>
First post2016-02-25 23:44 -0800
Last post2016-02-26 06:27 -0800
Articles 3 — 3 participants

Back to article view | Back to comp.lang.python


Contents

  Cycling through iterables diagonally Pablo Lucena <plucena24@gmail.com> - 2016-02-25 23:44 -0800
    Re: Cycling through iterables diagonally Jussi Piitulainen <jussi.piitulainen@helsinki.fi> - 2016-02-26 11:21 +0200
    Re: Cycling through iterables diagonally marco.nawijn@colosso.nl - 2016-02-26 06:27 -0800

#103530 — Cycling through iterables diagonally

FromPablo Lucena <plucena24@gmail.com>
Date2016-02-25 23:44 -0800
SubjectCycling through iterables diagonally
Message-ID<mailman.142.1456472649.20994.python-list@python.org>
Hello,

I am trying to accomplish the following:

Say I have a group of 4 lists as follows:

l1 = ['a1', 'a2', 'a3', 'a4']
l2 = ['b1', 'b2', 'b3', 'b4']
l3 = ['c1', 'c2', 'c3', 'c4']
l4 = ['d1', 'd2', 'd3', 'd4']

I would like to cycle through these lists "diagonally" in groups of
len(list) (in this example, each list has 4 items).

cycle1: a1, b2, b3, b4
cycle2: a2, b3, c4, d1
cycle3: a3, b4, c1, d2
cycle4: a4, b1, c2, d3

The way I thought about doing this is as follows:

from collections import deque
from itertools import cycle

l1 = deque(['a1', 'a2', 'a3', 'a4'])
l2 = deque(['b1', 'b2', 'b3', 'b4'])
l3 = deque(['c1', 'c2', 'c3', 'c4'])
l4 = deque(['d1', 'd2', 'd3', 'd4'])

l1.rotate(-0)
l2.rotate(-1)
l3.rotate(-2)
l4.rotate(-3)

groups = cycle([l1, l2, l3, l4])

In [115]: for group in groups:
   .....:     if not group:
   .....:         break
   .....:     print(group.popleft())
   .....:
a1
b2
c3
d4
a2
b3
c4
d1
a3
b4
c1
d2
a4
b1
c2
d3

Prior to this I was mucking around with index counting while looping, and
popping lists out of a deque, popping an item out of the list, and
appending the list back into the deque during each iteration.

Is there a better/cleaner way to do this? I was hoping for some cool
itertools logic =)

Thanks!


-- 
*Pabl​o​*

[toc] | [next] | [standalone]


#103531

FromJussi Piitulainen <jussi.piitulainen@helsinki.fi>
Date2016-02-26 11:21 +0200
Message-ID<lf5lh67u8rl.fsf@ling.helsinki.fi>
In reply to#103530
Pablo Lucena writes:

> Hello,
>
> I am trying to accomplish the following:
>
> Say I have a group of 4 lists as follows:
>
> l1 = ['a1', 'a2', 'a3', 'a4']
> l2 = ['b1', 'b2', 'b3', 'b4']
> l3 = ['c1', 'c2', 'c3', 'c4']
> l4 = ['d1', 'd2', 'd3', 'd4']
>
> I would like to cycle through these lists "diagonally" in groups of
> len(list) (in this example, each list has 4 items).
>
> cycle1: a1, b2, b3, b4
> cycle2: a2, b3, c4, d1
> cycle3: a3, b4, c1, d2
> cycle4: a4, b1, c2, d3

First line should be a1, b2, c3, d4, right?

> The way I thought about doing this is as follows:
>
> from collections import deque
> from itertools import cycle

[...]

> Prior to this I was mucking around with index counting while looping,
> and popping lists out of a deque, popping an item out of the list, and
> appending the list back into the deque during each iteration.
>
> Is there a better/cleaner way to do this? I was hoping for some cool
> itertools logic =)

Here's a combination of itertools (chaining of slices for the rotations)
and builtin machinery (argument spreading, a generator expression, zip,
enumerate) that seems to have the desired effect.

from itertools import chain, islice

l1 = ['a1', 'a2', 'a3', 'a4']
l2 = ['b1', 'b2', 'b3', 'b4']
l3 = ['c1', 'c2', 'c3', 'c4']
l4 = ['d1', 'd2', 'd3', 'd4']

n = 4
chainfrom = chain.from_iterable
print(*chainfrom(zip(*(chain(islice(m, k, n),
                             islice(m, 0, k))
                       for k, m
                       in enumerate([l1, l2, l3, l4])))))

# prints: a1 b2 c3 d4 a2 b3 c4 d1 a3 b4 c1 d2 a4 b1 c2 d3

[toc] | [prev] | [next] | [standalone]


#103540

Frommarco.nawijn@colosso.nl
Date2016-02-26 06:27 -0800
Message-ID<bf52af34-abf6-43db-acac-8061f00f7764@googlegroups.com>
In reply to#103530
On Friday, February 26, 2016 at 8:44:38 AM UTC+1, Pablo Lucena wrote:
> Hello,
> 
> I am trying to accomplish the following:
> 
> Say I have a group of 4 lists as follows:
> 
> l1 = ['a1', 'a2', 'a3', 'a4']
> l2 = ['b1', 'b2', 'b3', 'b4']
> l3 = ['c1', 'c2', 'c3', 'c4']
> l4 = ['d1', 'd2', 'd3', 'd4']
> 
> I would like to cycle through these lists "diagonally" in groups of
> len(list) (in this example, each list has 4 items).
> 
> cycle1: a1, b2, b3, b4
> cycle2: a2, b3, c4, d1
> cycle3: a3, b4, c1, d2
> cycle4: a4, b1, c2, d3
> 
> The way I thought about doing this is as follows:
> 
> from collections import deque
> from itertools import cycle
> 
> l1 = deque(['a1', 'a2', 'a3', 'a4'])
> l2 = deque(['b1', 'b2', 'b3', 'b4'])
> l3 = deque(['c1', 'c2', 'c3', 'c4'])
> l4 = deque(['d1', 'd2', 'd3', 'd4'])
> 
> l1.rotate(-0)
> l2.rotate(-1)
> l3.rotate(-2)
> l4.rotate(-3)
> 
> groups = cycle([l1, l2, l3, l4])
> 
> In [115]: for group in groups:
>    .....:     if not group:
>    .....:         break
>    .....:     print(group.popleft())
>    .....:
> a1
> b2
> c3
> d4
> a2
> b3
> c4
> d1
> a3
> b4
> c1
> d2
> a4
> b1
> c2
> d3
> 
> Prior to this I was mucking around with index counting while looping, and
> popping lists out of a deque, popping an item out of the list, and
> appending the list back into the deque during each iteration.
> 
> Is there a better/cleaner way to do this? I was hoping for some cool
> itertools logic =)
> 
> Thanks!
> 
> 
> -- 
> *Pablo*

Hello Pablo,

If you don't mind using third-party packages you 
could this quite straighforward with numpy:
(Python 2.7)

import numpy as np

a = np.array([
  ('a1', 'a2', 'a3', 'a4'),
  ('b1', 'b2', 'b3', 'b4'),
  ('c1', 'c2', 'c3', 'c4'),
  ('d1', 'd2', 'd3', 'd4')], dtype=str)

nrows, ncols = a.shape

for i in range(ncols):
    print np.diag(np.roll(a, -i, axis=1))

This prints:

['a1' 'b2' 'c3' 'd4']
['a2' 'b3' 'c4' 'd1']
['a3' 'b4' 'c1' 'd2']
['a4' 'b1' 'c2' 'd3']

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web