2

I have a list like ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']

How do I reorder it based on every n item (e.g. every 4 items), so that it has the 1st item, then 5th item, then the 9th item, then the 2nd item, then the 6th item, then the 10th item, then the 3rd item, the 7th item, and the 11th item, then the 4th item, the 8th item, and the 12th item. (Yes, I'm sorry for starting to count by 1 instead of 0 in writing that out....)

['a', 'e', 'i', 'b', 'f', 'j', 'c', 'g', 'k']

John
  • 1,405
  • 2
  • 14
  • 21

5 Answers5

5

Updated:

Mark Tolonen is correct that the original solution only works in a few situations. Here is a corrected version:

>>> flatten = lambda x: reduce(lambda a,b: a+b, x)
>>> everyN = lambda N,l: flatten([l[s:][::N] for s in range(N)])

Note: flatten can be implemented in many ways (including itertools.chain.from_iterable).

Example usage:

>>> everyN(4, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k'])
['a', 'e', 'i', 'b', 'f', 'j', 'c', 'g', 'k', 'd', 'h']

>>> everyN(4, ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l'])
['a', 'e', 'i', 'b', 'f', 'j', 'c', 'g', 'k', 'd', 'h', 'l']

>>> everyN(2, ['a','b','c'])
['a', 'c', 'b']

Original solution:

>>> import itertools
>>> l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']
>>> step = 4
>>> list(itertools.islice(l*step, None, None, step))
['a', 'e', 'i', 'b', 'f', 'j', 'c', 'g', 'k', 'd', 'h']

Note that the list() call is usually not necessary since most things that take a list will also take an iterator object. But it is convenient for displaying the result.

Community
  • 1
  • 1
kanaka
  • 70,845
  • 23
  • 144
  • 140
2

I doubt this is the most performant or elegant solution, but it does work:

>>>lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']
>>>lst[::4] + lst[1::4] + lst[2::4] + lst[3::4]
['a', 'e', 'i', 'b', 'f', 'j', 'c', 'g', 'k', 'd', 'h']
Brenden Brown
  • 3,125
  • 1
  • 14
  • 15
1

You could do this:

    l = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']
    f = []
    n = 4

    for i in range(n):
        f.extend(l[i::n])
jpm
  • 156
  • 1
  • 5
1

This supports any length list with any N step:

from itertools import islice

def reorder(L,N):
    return [x for n in range(N) for x in islice(L,n,None,N)]

L = list(range(16))
for N in range(1,9):
    print(N,reorder(L,N))

L = list('abcdefghijk')
for N in range(1,9):
    print(N,reorder(L,N))

Output:

1 [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
2 [0, 2, 4, 6, 8, 10, 12, 14, 1, 3, 5, 7, 9, 11, 13, 15]
3 [0, 3, 6, 9, 12, 15, 1, 4, 7, 10, 13, 2, 5, 8, 11, 14]
4 [0, 4, 8, 12, 1, 5, 9, 13, 2, 6, 10, 14, 3, 7, 11, 15]
5 [0, 5, 10, 15, 1, 6, 11, 2, 7, 12, 3, 8, 13, 4, 9, 14]
6 [0, 6, 12, 1, 7, 13, 2, 8, 14, 3, 9, 15, 4, 10, 5, 11]
7 [0, 7, 14, 1, 8, 15, 2, 9, 3, 10, 4, 11, 5, 12, 6, 13]
8 [0, 8, 1, 9, 2, 10, 3, 11, 4, 12, 5, 13, 6, 14, 7, 15]
1 ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']
2 ['a', 'c', 'e', 'g', 'i', 'k', 'b', 'd', 'f', 'h', 'j']
3 ['a', 'd', 'g', 'j', 'b', 'e', 'h', 'k', 'c', 'f', 'i']
4 ['a', 'e', 'i', 'b', 'f', 'j', 'c', 'g', 'k', 'd', 'h']
5 ['a', 'f', 'k', 'b', 'g', 'c', 'h', 'd', 'i', 'e', 'j']
6 ['a', 'g', 'b', 'h', 'c', 'i', 'd', 'j', 'e', 'k', 'f']
7 ['a', 'h', 'b', 'i', 'c', 'j', 'd', 'k', 'e', 'f', 'g']
8 ['a', 'i', 'b', 'j', 'c', 'k', 'd', 'e', 'f', 'g', 'h']
Mark Tolonen
  • 166,664
  • 26
  • 169
  • 251
1

You can do it with a simple one-liner:

lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k']
every4 = [s for i in range(4) for s in lst[i::4]]

This is a simple rewriting of James Moriarty's solution.

davidedb
  • 867
  • 5
  • 12