Idiomatic way of repeating items in a sequence.

A

alr

I need to repeat each item in a list n times, like this function does:

def repeatitems(sequence, repetitions):
newlist = []
for item in sequence:
for i in range(repetitions):
newlist.append(item)
return newlist

Output:
>>> repeatitems(['a', 'b', 'c'], 3)
['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c']

Clear and simple. But i wonder if there is a more idiomatic way. Surely not this:

def repeatitems(sequence, repetitions):
return reduce(lambda l, i: l + i, [[item] * repetitions for item in sequence])

?
 
M

Max M

alr said:
I need to repeat each item in a list n times, like this function does:

def repeatitems(sequence, repetitions):
newlist = []
for item in sequence:
for i in range(repetitions):
newlist.append(item)
return newlist


I would make just a minor change:

def repeatitems(sequence, repetitions):
newlist = []
for item in sequence:
newlist += repetitions*[item]
return newlist


regards Max M
 
D

Duncan Booth

(e-mail address removed) (alr) wrote in
I need to repeat each item in a list n times, like this function does:

def repeatitems(sequence, repetitions):
newlist = []
for item in sequence:
for i in range(repetitions):
newlist.append(item)
return newlist

Output:
repeatitems(['a', 'b', 'c'], 3)
['a', 'a', 'a', 'b', 'b', 'b', 'c', 'c', 'c']

Clear and simple. But i wonder if there is a more idiomatic way.

The most obvious one that springs to mind is just a slight simplification
of your version:

def repeatitems(sequence, repetitions):
newlist = []
for item in sequence:
newlist.extend([item] * repetitions)
return newlist
 
P

Peter Otten

alr said:
I need to repeat each item in a list n times, like this function does:

def repeatitems(sequence, repetitions):
newlist = []
for item in sequence:
for i in range(repetitions):
newlist.append(item)
return newlist
....
But i wonder if there is a more idiomatic way.

How about this?

def repeatItems(sequence, repetitions):
return [[item]*repetitions for item in sequence]
 
R

Richard Brodie

Peter Otten said:
How about this?

def repeatItems(sequence, repetitions):
return [[item]*repetitions for item in sequence]

Unfortunately that is equivalent to:

def repeatitems(sequence, repetitions):
newlist = []
for item in sequence:
newlist.append([item] * repetitions)
return newlist

and not:

def repeatitems(sequence, repetitions):
newlist = []
for item in sequence:
newlist.extend([item] * repetitions)
return newlist
 
D

Duncan Booth

The most obvious one that springs to mind is just a slight
simplification of your version:

def repeatitems(sequence, repetitions):
newlist = []
for item in sequence:
newlist.extend([item] * repetitions)
return newlist

Or, if you are in a "I've got a new toy to play with" mood you could use
itertools from Python 2.3 to obfuscate it somewhat:

from itertools import chain, izip, repeat
def repeatiterate(sequence, repetitions):
return chain(*izip(*repeat(sequence, repetitions)))

This version returns an iterator, so you might want to throw in a call to
'list' if you want to do anything other than iterating over the result.
 
P

Peter Otten

Richard Brodie wrote:
Unfortunately that is equivalent to:

def repeatitems(sequence, repetitions):
newlist = []
for item in sequence:
newlist.append([item] * repetitions)
return newlist

.... but it looked so good. I should have tested it, though.
Je suis desole :-(
 
T

Terry Reedy

alr said:
I need to repeat each item in a list n times, like this function
does:

Is this really the right question? Any code that requires such an
n-repeat list *could* be rewritten (if you own it) to use the replist
in condensed form: (items, n). If this is not possible, one could
also define a replist class with a __getitem__(self, index) that
divides index by self.n and an __iter__() that returns an appropriate
generator.

Terry J. Reedy
 
J

John Hunter

alr> reduce(lambda l, i: l + i, [[item] * repetitions for item in

This doesn't look too bad to me, but perhaps list comprehensions are
clearer?

seq = ['a', 'b', 'c']
print [x for x in seq for x in seq]
 
J

John Hunter

alr> reduce(lambda l, i: l + i, [[item] * repetitions for item in
alr> sequence])


Oops, premature hit of send key. What I meant to say was

seq = ['a', 'b', 'c']
print [x for x in seq for i in range(len(seq))]

JDH
 
J

Jeff Epler

Here's one:

def repeatitems(sequence, repetitions):
r = [None] * repetitions
return [i for i in sequence for j in r]

Here's another, using generator functions (so the return is an iterator,
not a list):

def repeatitems(sequence, repetitions):
r = [None] * repetitions
for item in sequence:
for i in r:
yield item

In both cases I've performed an "optimization" by precomputing a list
with len(repetitions) instead of computing it once for each item in
sequence. Whether this makes a difference, I don't know.

Jeff
 
M

Mike C. Fletcher

John said:
This doesn't look too bad to me, but perhaps list comprehensions are
clearer?

seq = ['a', 'b', 'c']
print [x for x in seq for x in seq]
.... return [x for x in sequence for i in range(count) ]
....
[2, 2, 2, 3, 3, 3, 4, 4, 4]

I *think* is what you were suggesting, and is indeed very clear. For
those into generators, this is fun (but has no huge advantage if you
wind up using repeat instead of irepeat, or if you're using small
sequences):
.... countSet = range(count)
.... for item in sequence:
.... for i in countSet:
.... yield item
........ return list(irepeat(sequence, count))
....
[2, 2, 2, 3, 3, 3, 4, 4, 4]

Enjoy,
Mike

_______________________________________
Mike C. Fletcher
Designer, VR Plumber, Coder
http://members.rogers.com/mcfletch/
 
A

alr

Wow, tanks for alle the replies. My favourite is John Hunters/Bob
Gailers solution ([x for x in seq for i in range(repetitions)]). I had
forgotten that you could have nested for statements in list
literals... Aahz's point is taken. I happen to need to repeat lists of
strings (which are immutable), but that's not what i asked about now
is it. :)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,596
Members
45,141
Latest member
BlissKeto
Top