Insert item before each element of a list

M

mooremathewl

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
 
I

Ian Kelly

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))
 
M

MRAB

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))
 
I

Ian Kelly

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
good comments, too.

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.
 
P

Peter Otten

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]
 
P

Prasad, Ramit

Agon said:
Sent: Monday, October 08, 2012 3:12 PM
To: (e-mail address removed)
Subject: Re: Insert item before each element of a list

[('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.
 
A

Agon Hajdari

Agon said:
Sent: Monday, October 08, 2012 3:12 PM
To: (e-mail address removed)
Subject: Re: Insert item before each element of a list

[('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)]
 
P

Prasad, Ramit

Agon said:
Agon said:
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
map instead.

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.
 
A

Alex

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."
 
T

Terry Reedy

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.append('insert me')
lst.append(item)
['insert me', 1, 'insert me', 2, 'insert me', 3]

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

Roy Smith

Terry Reedy said:
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.
 
R

rusi

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.


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]
 
S

Steven D'Aprano

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]
 
P

Peter Otten

Duncan said:
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

http://thread.gmane.org/gmane.comp.python.general/718940/focus=718947

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.
 
M

mooremathewl

(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!
 

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,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top