0

I have some code here:

lsp_rows = ['a', 'b', 'c', 'd', 'e', 'b', 'c', 'd', 'e', 'a', 'c', 
            'd', 'e', 'a', 'b', 'd', 'e', 'a', 'b', 'c', 'e', 'a', 
            'b', 'c', 'd']
n = int(width/length)
x = [a+b+c+d+e for a,b,c,d,e in zip(*[iter(lsp_rows)]*n)]

Currently, this will split my list "lsp_rows" in groups of 5 all the time as my n = 5. But I need it to split differently depending on "n" as it will change depending on the values of width and length. So if n is 4 i need the list to split into 4's.

I can see that the problem is with the "a+b+c+d+e for a,b,c,d,e", and I don't know a way to make this change without my manual input, is there a way for me to solve this.

If you guys could explain as thoroughly as possible i'd really appreciate it as i'm pretty new to python. Thanks in advance!

uuh lud
  • 17
  • 3
  • Maybe try use [this](https://stackoverflow.com/questions/509211/explain-slice-notation) in a for loop? – Yonlif Jun 14 '17 at 17:43
  • I don't understand, what is the problem? Why don't you wrap this in a function passing in whatever parameters you need? – juanpa.arrivillaga Jun 14 '17 at 17:45
  • Give a sample of `lsp_rows`. What do the elements `a` etc look like - list, strings, numbers? Also, can you explain the expression that you are using? It looks a bit 'advanced' for someone new to Python. – hpaulj Jun 14 '17 at 18:06
  • @hpaulj: ive edited the question to show what lsp_rows looks like – uuh lud Jun 14 '17 at 18:58
  • 1
    With strings `join` is better than `+` – hpaulj Jun 14 '17 at 20:48

2 Answers2

2

I believe this will generalize your expression to n items:

import functools
import operator
[functools.reduce(operator.add,abc) for abc in zip(*[iter(x)]*n)]

though I'd still like see a test case.

For example if x is a list of lists, the result is a list of x flattened.

A list of numbers or a string look better:

In [394]: [functools.reduce(operator.add,abc) for abc in zip(*[iter('abcdefghij')]*4)]
Out[394]: ['abcd', 'efgh']
In [395]: [functools.reduce(operator.add,abc) for abc in zip(*[iter('abcdefghij')]*5)]
Out[395]: ['abcde', 'fghij']
In [396]: [functools.reduce(operator.add,abc) for abc in zip(*[iter(range(20))]*5)]
Out[396]: [10, 35, 60, 85]

with your list of characters

In [400]: [functools.reduce(operator.add,abc) for abc in zip(*[iter(lsp_rows)]*5)]
Out[400]: ['abcde', 'bcdea', 'cdeab', 'deabc', 'eabcd']
In [401]: [functools.reduce(operator.add,abc) for abc in zip(*[iter(lsp_rows)]*6)]
Out[401]: ['abcdeb', 'cdeacd', 'eabdea', 'bceabc']

All these imports can be replaced with join if the items are strings.

hpaulj
  • 221,503
  • 14
  • 230
  • 353
  • Don't need to import operator.add, instead just do: [functools.reduce(lambda x, y: x + y, abc) for abc in zip(*[iter(x)] * n)] – Pedro Boechat Jun 14 '17 at 21:25
  • yeah, you're right... and it seems to be slightly faster too: https://stackoverflow.com/questions/467920/in-what-situation-should-the-built-in-operator-module-be-used-in-python – Pedro Boechat Jun 16 '17 at 14:16
2

With strings only you can:

[''.join(t) for t in zip(*[iter(lsp_rows)]*n)]

Or slightly more succinct and possibly less memory usage:

map(''.join, zip(*[iter(lsp_rows)]*n))

The answer provided by @hpaulj is more useful in the general case.

And, on the off-chance that you're just trying to generate the cycles of a string, the following will produce the same output.

s = 'abcde'
[s[i:] + s[:i] for i in range(len(s))]
Jared Goguen
  • 8,772
  • 2
  • 18
  • 36