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
    #1
    1. Advertising

  2. Ian Kelly Guest

    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
    #2
    1. Advertising

  3. MRAB Guest

    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
    #3
  4. Ian Kelly Guest

    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
    > 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.
     
    Ian Kelly, Oct 8, 2012
    #4
  5. Agon Hajdari Guest

    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
    #5
  6. Peter Otten Guest

    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
    #6
  7. 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.
     
    Prasad, Ramit, Oct 8, 2012
    #7
  8. Agon Hajdari Guest

    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
    #8
  9. 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
    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.
     
    Prasad, Ramit, Oct 8, 2012
    #9
  10. Paul Rubin Guest

    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
    #10
  11. Nobody Guest

    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
    #11
  12. Alex Guest

    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
    #12
  13. Terry Reedy Guest

    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
    #13
  14. Roy Smith Guest

    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
    #14
  15. rusi Guest

    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.


    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]
     
    rusi, Oct 9, 2012
    #15
  16. rusi Guest

    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
    #16
  17. alex23 Guest

    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
    #17
  18. 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
    #18
  19. Peter Otten Guest

    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

    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.
     
    Peter Otten, Oct 9, 2012
    #19
  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
    #20
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    5
    Views:
    490
  2. Replies:
    0
    Views:
    333
  3. HANM
    Replies:
    2
    Views:
    753
    Joseph Kesselman
    Jan 29, 2008
  4. Ann
    Replies:
    0
    Views:
    169
  5. Pat Maddox
    Replies:
    6
    Views:
    165
    Marcin Mielżyński
    Jan 20, 2006
Loading...

Share This Page