# Insert item before each element of a list

Discussion in 'Python' started by mooremathewl@gmail.com, Oct 8, 2012.

1. ### Guest

What's the best way to accomplish this? Am I over-complicating it? My gut feeling is there is a better way than the following:

>>> import itertools
>>> x = [1, 2, 3]
>>> y = list(itertools.chain.from_iterable(('insertme', x) for i in range(len(x))))
>>> y

['insertme', 1, 'insertme', 2, 'insertme', 3]

I appreciate any and all feedback.

--Matt

, Oct 8, 2012

2. ### Ian KellyGuest

On Mon, Oct 8, 2012 at 1:28 PM, <> wrote:
> What's the best way to accomplish this? Am I over-complicating it? My gut feeling is there is a better way than the following:
>
>>>> import itertools
>>>> x = [1, 2, 3]
>>>> y = list(itertools.chain.from_iterable(('insertme', x) for i in range(len(x))))
>>>> y

> ['insertme', 1, 'insertme', 2, 'insertme', 3]
>
> I appreciate any and all feedback.

Using the "roundrobin" recipe from the itertools documentation:

x = [1, 2, 3]
y = list(roundrobin(itertools.repeat('insertme', len(x)), x))

Ian Kelly, Oct 8, 2012

3. ### MRABGuest

On 2012-10-08 20:28, wrote:
> What's the best way to accomplish this? Am I over-complicating it? My gut feeling is there is a better way than the following:
>
>>>> import itertools
>>>> x = [1, 2, 3]
>>>> y = list(itertools.chain.from_iterable(('insertme', x) for i in range(len(x))))
>>>> y

> ['insertme', 1, 'insertme', 2, 'insertme', 3]
>
> I appreciate any and all feedback.
>

Slightly better is:

y = list(itertools.chain.from_iterable(('insertme', i) for i in x))

MRAB, Oct 8, 2012
4. ### Ian KellyGuest

On Mon, Oct 8, 2012 at 1:52 PM, Joshua Landau
<> wrote:
> But it's not far. I wouldn't use Ian Kelly's method (no offence), because of
> len(x): it's less compatible with iterables. Others have ninja'd me with

That's fair, I probably wouldn't use it either. It points to a
possible need for a roundrobin variant that truncates like zip when
one of the iterables runs out. It would have to do some look-ahead,
but it would remove the need for the len(x) restriction on
itertools.repeat.

Ian Kelly, Oct 8, 2012
5. ### Agon HajdariGuest

On 10/08/2012 09:45 PM, Chris Kaynor wrote:
> [('insertme', i) for i in x]

This is not enough, you have to merge it afterwards.

y = [item for tup in y for item in tup]

Agon Hajdari, Oct 8, 2012
6. ### Peter OttenGuest

wrote:

> What's the best way to accomplish this? Am I over-complicating it? My
> gut feeling is there is a better way than the following:
>
>>>> import itertools
>>>> x = [1, 2, 3]
>>>> y = list(itertools.chain.from_iterable(('insertme', x) for i in
>>>> range(len(x)))) y

> ['insertme', 1, 'insertme', 2, 'insertme', 3]

Less general than chain.from_iterable(izip(repeat("insertme"), x)):

>>> x = [1, 2, 3]
>>> y = 2*len(x)*["insertme"]
>>> y[1::2] = x
>>> y

['insertme', 1, 'insertme', 2, 'insertme', 3]

Peter Otten, Oct 8, 2012

Agon Hajdari wrote:

> Sent: Monday, October 08, 2012 3:12 PM
> To:
> Subject: Re: Insert item before each element of a list
>
> On 10/08/2012 09:45 PM, Chris Kaynor wrote:

> > [('insertme', i) for i in x]

>
> This is not enough, you have to merge it afterwards.

Why do you say that? It seems to work just fine for me.

>>> x

[0, 1, 2, 3, 4]

>>> [('insertme', i) for i in x]

[('insertme', 0), ('insertme', 1), ('insertme', 2), ('insertme', 3), ('insertme', 4)]

>
> y = [item for tup in y for item in tup]
>

This email is confidentialand subject to important disclaimers and
conditions including on offers for the purchase or sale of
securities, accuracy and completeness of information, viruses,
confidentiality, legal privilege, and legal entity disclaimers,
available at http://www.jpmorgan.com/pages/disclosures/email.

8. ### Agon HajdariGuest

On 10/08/2012 11:15 PM, Prasad, Ramit wrote:
> Agon Hajdari wrote:
>> Sent: Monday, October 08, 2012 3:12 PM
>> To:
>> Subject: Re: Insert item before each element of a list
>>
>> On 10/08/2012 09:45 PM, Chris Kaynor wrote:
>>> [('insertme', i) for i in x]

>>
>> This is not enough, you have to merge it afterwards.

>
> Why do you say that? It seems to work just fine for me.
>
>>>> x

> [0, 1, 2, 3, 4]
>>>> [('insertme', i) for i in x]

> [('insertme', 0), ('insertme', 1), ('insertme', 2), ('insertme', 3), ('insertme', 4)]
>
>>
>> y = [item for tup in y for item in tup]
>>

>
> This email is confidential and subject to important disclaimers and
> conditions including on offers for the purchase or sale of
> securities, accuracy and completeness of information, viruses,
> confidentiality, legal privilege, and legal entity disclaimers,
> available at http://www.jpmorgan.com/pages/disclosures/email.
>

I think he wanted to have a 'plain' list
a = [0, 1, 0, 2, 0, 3]
and not
a = [(0, 1), (0, 2), (0, 3)]

Agon Hajdari, Oct 8, 2012

Agon Hajdari wrote:

> On 10/08/2012 11:15 PM, Prasad, Ramit wrote:

> > Agon Hajdari wrote:

> >>
> >> On 10/08/2012 09:45 PM, Chris Kaynor wrote:
> >>> [('insertme', i) for i in x]
> >>
> >>This is not enough, you have to merge it afterwards.

> >
> > Why do you say that? It seems to work just fine for me.
> >

> >>>> x

> > [0, 1, 2, 3, 4]

> >>>> [('insertme', i) for i in x]

> > [('insertme', 0), ('insertme', 1), ('insertme', 2), ('insertme', 3),('insertme', 4)]
> >

> >>
> >> y = [item for tup in y foritem in tup]

>
> I think he wanted to have a 'plain' list
> a = [0, 1, 0, 2, 0, 3]
> and not
> a = [(0, 1), (0, 2), (0,3)]

You are absolutely correct. I missed that when I tried it.
Instead of the nested list comprehension, I might have used

>>> y = [('insertme', i) for i in x]
>>> z = []
>>> _ = map( z.extend, y )
>>> z

['insertme', 0, 'insertme', 1, 'insertme', 2, 'insertme', 3, 'insertme', 4]

I amnot sure which is more Pythonic, but to me map + list.extend tells
me more explicitly that I am dealing with an iterable of iterables.
It might make more sense to only to me though.

This email is confidential and subject to important disclaimers and
conditions including on offers for the purchase or sale of
securities, accuracy and completeness of information, viruses,
confidentiality, legal privilege, and legal entity disclaimers,
available at http://www.jpmorgan.com/pages/disclosures/email.

10. ### Paul RubinGuest

writes:
>>>> x = [1, 2, 3] ..
>>>> y

> ['insertme', 1, 'insertme', 2, 'insertme', 3]

def ix(prefix, x):
for a in x:
yield prefix
yield a

y = list(ix('insertme', x))

================

from itertools import *
y = list(chain.from_iterable(izip(repeat('insertme'), x)))

================

etc.

Paul Rubin, Oct 8, 2012
11. ### NobodyGuest

On Mon, 08 Oct 2012 12:28:43 -0700, mooremathewl wrote:

>>>> import itertools
>>>> x = [1, 2, 3]
>>>> y = list(itertools.chain.from_iterable(('insertme', x) for i in
>>>> range(len(x)))) y

> ['insertme', 1, 'insertme', 2, 'insertme', 3]

>>> [i for j in [1,2,3] for i in ('insertme', j)]

['insertme', 1, 'insertme', 2, 'insertme', 3]

Nobody, Oct 8, 2012
12. ### AlexGuest

wrote:

> What's the best way to accomplish this? Am I over-complicating it?
> My gut feeling is there is a better way than the following:
>
> >>> import itertools
> >>> x = [1, 2, 3]
> >>> y = list(itertools.chain.from_iterable(('insertme', x) for i

> in range(len(x)))) >>> y
> ['insertme', 1, 'insertme', 2, 'insertme', 3]
>
> I appreciate any and all feedback.
>
> --Matt

Just like the Zen of Python (http://www.python.org/dev/peps/pep-0020/)
says . . . "There should be at least ten-- and preferably more --clever
and obscure ways to do it."

Alex, Oct 9, 2012
13. ### Terry ReedyGuest

On 10/8/2012 3:28 PM, wrote:
> What's the best way to accomplish this? Am I over-complicating it? My gut feeling is there is a better way than the following:
>
>>>> import itertools
>>>> x = [1, 2, 3]
>>>> y = list(itertools.chain.from_iterable(('insertme', x) for i in range(len(x))))
>>>> y

> ['insertme', 1, 'insertme', 2, 'insertme', 3]

The straightforward, crystal-clear, old-fashioned way

>>> lst = []
>>> for item in [1,2,3]:

lst.append('insert me')
lst.append(item)

>>> lst

['insert me', 1, 'insert me', 2, 'insert me', 3]

Paul Rubin's list(gfunc(prefix, lst)) is similar in execution.

--
Terry Jan Reedy

Terry Reedy, Oct 9, 2012
14. ### Roy SmithGuest

In article <>,
Terry Reedy <> wrote:

> On 10/8/2012 3:28 PM, wrote:
> > What's the best way to accomplish this? Am I over-complicating it? My gut
> > feeling is there is a better way than the following:
> >
> >>>> import itertools
> >>>> x = [1, 2, 3]
> >>>> y = list(itertools.chain.from_iterable(('insertme', x) for i in
> >>>> range(len(x))))
> >>>> y

> > ['insertme', 1, 'insertme', 2, 'insertme', 3]

>
> The straightforward, crystal-clear, old-fashioned way
>
> >>> lst = []
> >>> for item in [1,2,3]:

> lst.append('insert me')
> lst.append(item)

I'm going to go with this one. I think people tend to over-abuse list
comprehensions. They're a great shorthand for many of the most common
use cases, but once you stray from the simple examples, you quickly end
up with something totally obscure.

> y = list(itertools.chain.from_iterable(('insertme', x) for i in range(len(x))))

A statement ending in four close parens is usually going to be pretty
difficult to figure out. This is one where I had to pull out my pencil
and start pairing them off manually to figure out how to parse it.

Roy Smith, Oct 9, 2012
15. ### rusiGuest

On Oct 9, 7:06 am, Roy Smith <> wrote:
> In article <>,
>  Terry Reedy <> wrote:
>
>
>
>
>
>
>
>
>
> > On 10/8/2012 3:28 PM, wrote:
> > > What's the best way to accomplish this?  Am I over-complicating it? My gut
> > > feeling is there is a better way than the following:

>
> > >>>> import itertools
> > >>>> x = [1, 2, 3]
> > >>>> y = list(itertools.chain.from_iterable(('insertme', x) for i in
> > >>>> range(len(x))))
> > >>>> y
> > > ['insertme', 1, 'insertme', 2, 'insertme', 3]

>
> > The straightforward, crystal-clear, old-fashioned way

>
> >  >>> lst = []
> >  >>> for item in [1,2,3]:
> >    lst.append('insert me')
> >    lst.append(item)

>
> I'm going to go with this one.  I think people tend to over-abuse list
> comprehensions.  They're a great shorthand for many of the most common
> use cases, but once you stray from the simple examples, you quickly end
> up with something totally obscure.
>
> > y = list(itertools.chain.from_iterable(('insertme', x) for i in range(len(x))))

>
> A statement ending in four close parens is usually going to be pretty
> difficult to figure out.  This is one where I had to pull out my pencil
> and start pairing them off manually to figure out how to parse it.

>>> x = [1,2,3]
>>> reduce(operator.add, [['insert', a] for a in x])

['insert', 1, 'insert', 2, 'insert', 3]

rusi, Oct 9, 2012
16. ### rusiGuest

On Oct 9, 7:34 am, rusi <> wrote:
> How about a 2-paren version?
>
> >>> x = [1,2,3]
> >>> reduce(operator.add,  [['insert', a] for a in x])

>
> ['insert', 1, 'insert', 2, 'insert', 3]

Or if one prefers the different parens on the other side:

>>> reduce(operator.add, (['insert', a] for a in x))

['insert', 1, 'insert', 2, 'insert', 3]

rusi, Oct 9, 2012
17. ### alex23Guest

On Oct 9, 12:06 pm, Roy Smith <> wrote:
> I'm going to go with this one.  I think people tend to over-abuse list
> comprehensions.

I weep whenever I find `_ = [...]` in other people's code.

alex23, Oct 9, 2012
18. ### Steven D'ApranoGuest

On Mon, 08 Oct 2012 19:34:26 -0700, rusi wrote:

> How about a 2-paren version?
>
>>>> x = [1,2,3]
>>>> reduce(operator.add, [['insert', a] for a in x])

> ['insert', 1, 'insert', 2, 'insert', 3]

That works, but all those list additions are going to be slow. It will be
an O(N**2) algorithm.

If you're going to be frequently interleaving sequences, a helper
function is a good solution. Here's my muxer:

def mux(*iterables):
"""Muxer which yields items interleaved from each iterator or
sequence argument, stopping when the first one is exhausted.

>>> list( mux([1,2,3], range(10, 15), "ABCD") )

[1, 10, 'A', 2, 11, 'B', 3, 12, 'C']
"""
for i in itertools.izip(*iterables): # in Python 3 use builtin zip
for item in i:
yield item

Then call it like this:

py> list(mux(itertools.repeat("insert me"), range(5)))
['insert me', 0, 'insert me', 1, 'insert me', 2, 'insert me', 3, 'insert
me', 4]

--
Steven

Steven D'Aprano, Oct 9, 2012
19. ### Peter OttenGuest

Duncan Booth wrote:

> wrote:
>
>> What's the best way to accomplish this? Am I over-complicating it?
>> My gut feeling is there is a better way than the following:
>>
>>>>> import itertools
>>>>> x = [1, 2, 3]
>>>>> y = list(itertools.chain.from_iterable(('insertme', x) for i in
>>>>> range(len(x)))) y

>> ['insertme', 1, 'insertme', 2, 'insertme', 3]
>>
>> I appreciate any and all feedback.
>>

>
> Given the myriad of proposed solutions, I'm surprised nobody has suggested
> good old list slicing:

My post on gmane

apparently didn't make it through to the list.

>>>> x = [1,2,3]
>>>> y = ['insertme']*(2*len(x))
>>>> y[1::2] = x
>>>> y

> ['insertme', 1, 'insertme', 2, 'insertme', 3]

An advantage of this approach -- it is usually much faster.

Peter Otten, Oct 9, 2012
20. ### Guest

On Monday, October 8, 2012 10:06:50 PM UTC-4, Roy Smith wrote:
> In article <>,
>

(big snip)

>
>
> > y = list(itertools.chain.from_iterable(('insertme', x) for i in range(len(x))))

>
>
>
> A statement ending in four close parens is usually going to be pretty
>
> difficult to figure out. This is one where I had to pull out my pencil
>
> and start pairing them off manually to figure out how to parse it.

Fair enough. I admit I was looking for a tricky one-liner, which rarely leads to good code...I should know better.

Thanks for all the feedback from everyone. It's amazing how much Python one can learn just asking about a small section of code!

, Oct 9, 2012