Converting a flat list to a list of tuples

Discussion in 'Python' started by metiu uitem, Nov 22, 2005.

  1. metiu uitem

    metiu uitem Guest

    Say you have a flat list:
    ['a', 1, 'b', 2, 'c', 3]

    How do you efficiently get
    [['a', 1], ['b', 2], ['c', 3]]

    I was thinking of something along the lines of:
    for (key,number) in list:
    print key, number

    but it's not working...

    Thank you
    metiu uitem, Nov 22, 2005
    #1
    1. Advertising

  2. metiu uitem

    Duncan Booth Guest

    metiu uitem wrote:

    > Say you have a flat list:
    > ['a', 1, 'b', 2, 'c', 3]
    >
    > How do you efficiently get
    > [['a', 1], ['b', 2], ['c', 3]]


    That's funny, I thought your subject line said 'list of tuples'. I'll
    answer the question in the subject rather than the question in the body:

    >>> aList = ['a', 1, 'b', 2, 'c', 3]
    >>> it = iter(aList)
    >>> zip(it, it)

    [('a', 1), ('b', 2), ('c', 3)]
    Duncan Booth, Nov 22, 2005
    #2
    1. Advertising

  3. On Tue, 22 Nov 2005 02:57:14 -0800, metiu uitem wrote:

    > Say you have a flat list:
    > ['a', 1, 'b', 2, 'c', 3]
    >
    > How do you efficiently get
    > [['a', 1], ['b', 2], ['c', 3]]


    def split_and_combine(L):
    newL = []
    for i in range(len(L)//2):
    newL.append( [L[2*i], L[2*i+1]] )
    return newL

    Another possibility is a list comprehension:

    L = ['a', 1, 'b', 2, 'c', 3]
    [[L, L[i+1]] for i in range(len(L)) if i%2 == 0]

    Personally, I think that's just about as complex as a single list
    comprehension should get. Otherwise it is too easy to create
    unmaintainable code.

    It is much easier (and probably faster) if you arrange matters so that you
    have two lists at the start:

    zip( ['a', 'b', 'c'], [1, 2, 3] )

    returns [('a', 1), ('b', 2), ('c', 3)]

    If you absolutely need the inner tuples to be lists, use a list
    comprehension afterwards:

    [list(t) for t in zip(['a', 'b', 'c'], [1, 2, 3])]


    --
    Steven.
    Steven D'Aprano, Nov 22, 2005
    #3
  4. metiu uitem

    metiu uitem Guest

    Thanks for the answer... yes the example was wrong!
    metiu uitem, Nov 22, 2005
    #4
  5. "metiu uitem" wrote:

    > Say you have a flat list:
    > ['a', 1, 'b', 2, 'c', 3]
    >
    > How do you efficiently get
    > [['a', 1], ['b', 2], ['c', 3]]


    simplest possible (works in all Python versions):

    L = ['a', 1, 'b', 2, 'c', 3]

    out = []
    for i in range(0, len(L), 2):
    out.append(L[i:i+2])

    or, on one line (works in all modern versions):

    out = [L[i:i+2] for i in range(0, len(L), 2)]

    or, from the slightly-silly-department:

    out = map(list, zip(L[0::2], L[1::2]))

    or, using the standard grouping pydiom:

    out = []; item = []
    for i in L:
    item.append(i)
    if len(item) == 2:
    out.append(item)
    item = []
    if item:
    out.append(item)

    etc.

    </F>
    Fredrik Lundh, Nov 22, 2005
    #5
  6. metiu uitem

    Guest

    Duncan Booth wrote:
    > metiu uitem wrote:
    >
    > > Say you have a flat list:
    > > ['a', 1, 'b', 2, 'c', 3]
    > >
    > > How do you efficiently get
    > > [['a', 1], ['b', 2], ['c', 3]]

    >
    > That's funny, I thought your subject line said 'list of tuples'. I'll
    > answer the question in the subject rather than the question in the body:
    >
    > >>> aList = ['a', 1, 'b', 2, 'c', 3]
    > >>> it = iter(aList)
    > >>> zip(it, it)

    > [('a', 1), ('b', 2), ('c', 3)]


    brilliant.
    , Nov 22, 2005
    #6
  7. metiu uitem wrote:

    > Say you have a flat list:
    > ['a', 1, 'b', 2, 'c', 3]
    >
    > How do you efficiently get
    > [['a', 1], ['b', 2], ['c', 3]]
    >
    > I was thinking of something along the lines of:
    > for (key,number) in list:
    > print key, number
    >
    > but it's not working...
    >
    > Thank you


    Hi,

    newList = zip(aList[::2], aList[1::2])
    newList
    [('a', 1), ('b', 2), ('c', 3)]

    Regards,

    Laurent.
    Laurent Rahuel, Nov 22, 2005
    #7
  8. On Tue, 22 Nov 2005 11:11:23 +0000, Duncan Booth wrote:

    >>>> aList = ['a', 1, 'b', 2, 'c', 3]
    >>>> it = iter(aList)
    >>>> zip(it, it)

    > [('a', 1), ('b', 2), ('c', 3)]


    I'm not sure if I should fall to my knees in admiration of a Cool Hack,
    or recoil in horror at a Bogus Kludge :)

    The code looks like it should return [('a', 'a'), (1, 1), ('b', 'b'), (2,
    2), ('c', 'c'), (3, 3)] but of course it does not: the arguments for zip
    are not independent.

    I guess it is more of a Neat Trick, with a dash of Gotcha For The Unwary.



    --
    Steven.
    Steven D'Aprano, Nov 22, 2005
    #8
  9. Duncan Booth wrote:

    > That's funny, I thought your subject line said 'list of tuples'. I'll
    > answer the question in the subject rather than the question in the body:
    >
    > >>> aList = ['a', 1, 'b', 2, 'c', 3]
    > >>> it = iter(aList)
    > >>> zip(it, it)

    > [('a', 1), ('b', 2), ('c', 3)]


    yesterday, we got locals()["_[1]"]. and now this ?

    is "relying on undefined behaviour" perhaps the new black ?

    and people are impressed? it's like my old Z80 days, when
    some folks thought it was truly amazing that call(11) printed
    the raw contents of the entire memory to the screen...

    </F>
    Fredrik Lundh, Nov 22, 2005
    #9
  10. * Duncan Booth <> wrote:

    > metiu uitem wrote:
    >
    > > Say you have a flat list:
    > > ['a', 1, 'b', 2, 'c', 3]
    > >
    > > How do you efficiently get
    > > [['a', 1], ['b', 2], ['c', 3]]

    >
    > That's funny, I thought your subject line said 'list of tuples'. I'll
    > answer the question in the subject rather than the question in the body:
    >
    > >>> aList = ['a', 1, 'b', 2, 'c', 3]
    > >>> it = iter(aList)
    > >>> zip(it, it)

    > [('a', 1), ('b', 2), ('c', 3)]


    Though it looks nice, it's an implementation dependant solution. What if
    someone changes zip to fetch the second item first?

    nd
    =?ISO-8859-1?Q?Andr=E9?= Malo, Nov 22, 2005
    #10
  11. metiu uitem

    Guest

    André Malo wrote:
    > * Duncan Booth <> wrote:
    >
    > > metiu uitem wrote:
    > >
    > > > Say you have a flat list:
    > > > ['a', 1, 'b', 2, 'c', 3]
    > > >
    > > > How do you efficiently get
    > > > [['a', 1], ['b', 2], ['c', 3]]

    > >
    > > That's funny, I thought your subject line said 'list of tuples'. I'll
    > > answer the question in the subject rather than the question in the body:
    > >
    > > >>> aList = ['a', 1, 'b', 2, 'c', 3]
    > > >>> it = iter(aList)
    > > >>> zip(it, it)

    > > [('a', 1), ('b', 2), ('c', 3)]

    >
    > Though it looks nice, it's an implementation dependant solution. What if
    > someone changes zip to fetch the second item first?
    >

    I believe someone should change the behaviour in the next release(is
    that 2.4.3 or 2.5?), then it will give us the hard lesson :)

    Just saying it is no good is not going to stop people from doing it.
    , Nov 22, 2005
    #11
  12. metiu uitem

    David Isaac Guest

    David Isaac, Nov 22, 2005
    #12
  13. "Laurent Rahuel" wrote:

    > Hi,
    >
    > newList = zip(aList[::2], aList[1::2])
    > newList
    > [('a', 1), ('b', 2), ('c', 3)]
    >
    > Regards,
    >
    > Laurent


    Or if aList can get very large and/or the conversion has to be
    performed many times:

    from itertools import islice
    newList = zip(islice(aList,0,None,2), islice(aList,1,None,2))

    George
    George Sakkis, Nov 22, 2005
    #13
  14. On 22 Nov 2005 11:11:23 GMT, Duncan Booth <> wrote:

    >metiu uitem wrote:
    >
    >> Say you have a flat list:
    >> ['a', 1, 'b', 2, 'c', 3]
    >>
    >> How do you efficiently get
    >> [['a', 1], ['b', 2], ['c', 3]]

    >
    >That's funny, I thought your subject line said 'list of tuples'. I'll
    >answer the question in the subject rather than the question in the body:
    >
    >>>> aList = ['a', 1, 'b', 2, 'c', 3]
    >>>> it = iter(aList)
    >>>> zip(it, it)

    >[('a', 1), ('b', 2), ('c', 3)]
    >

    Thank you for that. That is cool ;-)

    Regards,
    Bengt Richter
    Bengt Richter, Nov 22, 2005
    #14
  15. On Tue, 22 Nov 2005 13:26:45 +0100, "Fredrik Lundh" <> wrote:

    >Duncan Booth wrote:
    >
    >> That's funny, I thought your subject line said 'list of tuples'. I'll
    >> answer the question in the subject rather than the question in the body:
    >>
    >> >>> aList = ['a', 1, 'b', 2, 'c', 3]
    >> >>> it = iter(aList)
    >> >>> zip(it, it)

    >> [('a', 1), ('b', 2), ('c', 3)]

    >
    >yesterday, we got locals()["_[1]"]. and now this ?
    >

    I don't really think those are comparable.

    >is "relying on undefined behaviour" perhaps the new black ?

    Is it really undefined? If so, IMO it should be defined to
    do what it apparently does.
    >
    >and people are impressed? it's like my old Z80 days, when
    >some folks thought it was truly amazing that call(11) printed
    >the raw contents of the entire memory to the screen...
    >

    You really don't think it was cool? Or could be well defined? ;-)

    Hm, actually, something tells me I've seen some variation of this before,
    but I can't think of the context off hand.

    Regards,
    Bengt Richter
    Bengt Richter, Nov 22, 2005
    #15
  16. On Tue, 22 Nov 2005 13:37:06 +0100, =?ISO-8859-1?Q?Andr=E9?= Malo <> wrote:

    >* Duncan Booth <> wrote:
    >
    >> metiu uitem wrote:
    >>
    >> > Say you have a flat list:
    >> > ['a', 1, 'b', 2, 'c', 3]
    >> >
    >> > How do you efficiently get
    >> > [['a', 1], ['b', 2], ['c', 3]]

    >>
    >> That's funny, I thought your subject line said 'list of tuples'. I'll
    >> answer the question in the subject rather than the question in the body:
    >>
    >> >>> aList = ['a', 1, 'b', 2, 'c', 3]
    >> >>> it = iter(aList)
    >> >>> zip(it, it)

    >> [('a', 1), ('b', 2), ('c', 3)]

    >
    >Though it looks nice, it's an implementation dependant solution. What if
    >someone changes zip to fetch the second item first?
    >

    That would be a counter-intuitive thing to do. Most things go left->right
    in order as the default assumption.

    Regards,
    Bengt Richter
    Bengt Richter, Nov 22, 2005
    #16
  17. On Tue, 22 Nov 2005 14:28:56 GMT, "David Isaac" <> wrote:

    >
    >"Duncan Booth" <> wrote in message
    >news:Xns971671CB0DA43duncanbooth@127.0.0.1...
    >> >>> aList = ['a', 1, 'b', 2, 'c', 3]
    >> >>> it = iter(aList)
    >> >>> zip(it, it)

    >> [('a', 1), ('b', 2), ('c', 3)]

    >
    >That behavior is currently an accident.
    >http://sourceforge.net/tracker/?group_id=5470&atid=105470&func=detail&aid=1121416
    >Alan Isaac
    >

    That says
    """
    ii. The other problem is easier to explain by example.
    Let it=iter([1,2,3,4]).
    What is the result of zip(*[it]*2)?
    The current answer is: [(1,2),(3,4)],
    but it is impossible to determine this from the docs,
    which would allow [(1,3),(2,4)] instead (or indeed
    other possibilities).
    """
    IMO left->right is useful enough to warrant making it defined behaviour,
    not an accident. Isn't it(),it() well defined for a given iterator?
    So is the question whether zip will access its referenced input iterators
    in some peculiar order? Is the order of zip(a,b) accesses to a and b
    undefined? If, so, IMO it's reasonable to make it defined as if

    >>> def zip(*args):

    ... return list(tuple([it.next() for it in its])
    ... for its in [[iter(a) for a in args]]
    ... for _ in iter(lambda:0,1))
    ...
    >>> aList = ['a', 1, 'b', 2, 'c', 3]
    >>> it = iter(aList)
    >>> zip(it, it)

    [('a', 1), ('b', 2), ('c', 3)]
    >>> it = iter(aList)
    >>> zip(it, it, it)

    [('a', 1, 'b'), (2, 'c', 3)]
    >>> it = iter(aList)
    >>> zip(it)

    [('a',), (1,), ('b',), (2,), ('c',), (3,)]
    >>> zip(range(3), range(4))

    [(0, 0), (1, 1), (2, 2)]
    >>> zip(range(4), range(3))

    [ (0, 0), (1, 1), (2, 2)]

    (I just hacked this out, so maybe it's not bullet-proof, but the point is,
    I think there's no reason not to define the behaviour of zip to cycle
    through its arguments in the intuitive way).

    Regards,
    Bengt Richter
    Bengt Richter, Nov 22, 2005
    #17
  18. metiu uitem

    Dave Hansen Guest

    On Tue, 22 Nov 2005 20:12:52 GMT in comp.lang.python,
    (Bengt Richter) wrote:

    >On Tue, 22 Nov 2005 13:26:45 +0100, "Fredrik Lundh" <> wrote:
    >
    >>Duncan Booth wrote:
    >>
    >>> That's funny, I thought your subject line said 'list of tuples'. I'll
    >>> answer the question in the subject rather than the question in the body:
    >>>
    >>> >>> aList = ['a', 1, 'b', 2, 'c', 3]
    >>> >>> it = iter(aList)
    >>> >>> zip(it, it)
    >>> [('a', 1), ('b', 2), ('c', 3)]

    >>

    [...]
    >
    >Hm, actually, something tells me I've seen some variation of this before,
    >but I can't think of the context off hand.


    Earlier this fall I posted a question about iterating over a sequence
    while modifying it. Google should bring it up.

    This strikes me as the same idea, only inside-out...

    Regards,
    -=Dave

    --
    Change is inevitable, progress is not.
    Dave Hansen, Nov 22, 2005
    #18
  19. On 22 Nov 2005 07:42:31 -0800, "George Sakkis" <> wrote:

    >"Laurent Rahuel" wrote:
    >
    >> Hi,
    >>
    >> newList = zip(aList[::2], aList[1::2])
    >> newList
    >> [('a', 1), ('b', 2), ('c', 3)]
    >>
    >> Regards,
    >>
    >> Laurent

    >
    >Or if aList can get very large and/or the conversion has to be
    >performed many times:
    >
    >from itertools import islice
    >newList = zip(islice(aList,0,None,2), islice(aList,1,None,2))
    >

    Or, if you want to include fractional groups at the end

    >>> aList = ['a', 1, 'b', 2, 'c', 3]
    >>> from itertools import groupby
    >>> def grouper(n):

    ... def git():
    ... while True:
    ... for _ in xrange(n): yield 0
    ... for _ in xrange(n): yield 1
    ... git = git()
    ... def grouper(_): return git.next()
    ... return grouper
    ...
    >>> [tuple(g) for _, g in groupby(aList, grouper(2))]

    [('a', 1), ('b', 2), ('c', 3)]
    >>> [tuple(g) for _, g in groupby(aList, grouper(3))]

    [('a', 1, 'b'), (2, 'c', 3)]
    >>> [tuple(g) for _, g in groupby(aList, grouper(4))]

    [('a', 1, 'b', 2), ('c', 3)]

    Regards,
    Bengt Richter
    Bengt Richter, Nov 22, 2005
    #19
  20. metiu uitem

    Guest

    Bengt Richter wrote:
    > On Tue, 22 Nov 2005 13:37:06 +0100, =?ISO-8859-1?Q?Andr=E9?= Malo <> wrote:
    >
    > >* Duncan Booth <> wrote:
    > >
    > >> metiu uitem wrote:
    > >>
    > >> > Say you have a flat list:
    > >> > ['a', 1, 'b', 2, 'c', 3]
    > >> >
    > >> > How do you efficiently get
    > >> > [['a', 1], ['b', 2], ['c', 3]]
    > >>
    > >> That's funny, I thought your subject line said 'list of tuples'. I'll
    > >> answer the question in the subject rather than the question in the body:
    > >>
    > >> >>> aList = ['a', 1, 'b', 2, 'c', 3]
    > >> >>> it = iter(aList)
    > >> >>> zip(it, it)
    > >> [('a', 1), ('b', 2), ('c', 3)]

    > >
    > >Though it looks nice, it's an implementation dependant solution. What if
    > >someone changes zip to fetch the second item first?
    > >

    > That would be a counter-intuitive thing to do. Most things go left->right
    > in order as the default assumption.
    >

    I have to admit that the poster was right as there is nothing stop the
    implementor to do it this way and still gives you the defined result of
    zip(). One scenario I can think of is that it can be implemented to run
    in parallel, taking "n" results from "n" streams at the same time and
    when all n arrived, pump the resultinging tuple out and repeat.

    Why it needs to be done this way or is it desirable is another story.

    And I doubt the current behaviour will go away, unless they really want
    to break some codes to make the point.
    , Nov 22, 2005
    #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. Steven Bethard
    Replies:
    38
    Views:
    661
  2. Replies:
    5
    Views:
    536
    Thomas J. Gritzan
    Oct 6, 2006
  3. tuples within tuples

    , Oct 26, 2007, in forum: Python
    Replies:
    12
    Views:
    546
    Dennis Lee Bieber
    Oct 27, 2007
  4. xera121
    Replies:
    8
    Views:
    698
    lolmc
    Sep 30, 2009
  5. Jon Reyes
    Replies:
    18
    Views:
    214
    Mitya Sirenef
    Feb 19, 2013
Loading...

Share This Page