Packing list elements into tuples

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Nickolay Kolev

    Packing list elements into tuples

    Hi all,

    I have a list whose length is a multiple of 3. I want to get a list of
    tuples each of which has 3 consecutive elements from the original list,
    thus packing the list into smaller packets. Like this:

    l = [1,2,3,4,5,6]

    tups = [(1,2,3), (4,5,6)]

    or

    l = [1,2,3,4,5,6,7,8 ,9]

    tups = [(1,2,3), (4,5,6), (7,8,9)]

    if i can dictionaries it would be even better:


    l = [1,2,3,4,5,6]

    tups = [
    {'first':1,'sec ond':2,'third': 3},
    {'first':4,'sec ond':5,'third': 6}
    ]

    and so on.

    Any ideas?

    Many thanks in advance!

    Cheers,
    -- Nickolay
  • Russell Blau

    #2
    Re: Packing list elements into tuples

    "Nickolay Kolev" <nmkolev@uni-bonn.de> wrote in message
    news:cmrcqq$rv4 $1@f1node01.rhr z.uni-bonn.de...[color=blue]
    > Hi all,
    >
    > I have a list whose length is a multiple of 3. I want to get a list of
    > tuples each of which has 3 consecutive elements from the original list,
    > thus packing the list into smaller packets. Like this:
    >
    > l = [1,2,3,4,5,6,7,8 ,9]
    >
    > tups = [(1,2,3), (4,5,6), (7,8,9)][/color]

    How's this? :
    [color=blue][color=green][color=darkred]
    >>> alist[/color][/color][/color]
    [1, 2, 3, 4, 5, 6, 7, 8, 9][color=blue][color=green][color=darkred]
    >>> tups = [tuple(alist[i:i+3]) for i in xrange(0, len(alist), 3)]
    >>> tups[/color][/color][/color]
    [(1, 2, 3), (4, 5, 6), (7, 8, 9)]

    [color=blue]
    >
    > if i can dictionaries it would be even better:
    >
    >
    > l = [1,2,3,4,5,6]
    >
    > tups = [
    > {'first':1,'sec ond':2,'third': 3},
    > {'first':4,'sec ond':5,'third': 6}
    > ][/color]

    Well, now that you've been introduced to the concept of list indexes and
    list comprehensions, I think that extending it to dictionaries is fairly
    simple.


    --
    I don't actually read my hotmail account, but you can replace hotmail with
    excite if you really want to reach me.


    Comment

    • Nickolay Kolev

      #3
      Re: Packing list elements into tuples

      Nickolay Kolev wrote:
      [color=blue]
      > Hi all,
      >
      > I have a list whose length is a multiple of 3. I want to get a list of
      > tuples each of which has 3 consecutive elements from the original list,
      > thus packing the list into smaller packets. Like this:[/color]

      I found it in the cookbook:


      It looks quite cryptic, could anyone give me some pointers at what
      exactly is going on in the function?

      Cheers,
      -- Nickolay

      Comment

      • Steven Bethard

        #4
        Re: Packing list elements into tuples

        Nickolay Kolev <nmkolev <at> uni-bonn.de> writes:[color=blue]
        > l = [1,2,3,4,5,6]
        >
        > tups = [(1,2,3), (4,5,6)][/color]

        My favorite idiom:
        [color=blue][color=green][color=darkred]
        >>> l = [1,2,3,4,5,6]
        >>> zip(*(iter(l),) *3)[/color][/color][/color]
        [(1, 2, 3), (4, 5, 6)][color=blue][color=green][color=darkred]
        >>> l = [1,2,3,4,5,6,7,8 ,9]
        >>> zip(*(iter(l),) *3)[/color][/color][/color]
        [(1, 2, 3), (4, 5, 6), (7, 8, 9)]

        If you want dicts, try:
        [color=blue][color=green][color=darkred]
        >>> l = [1,2,3,4,5,6]
        >>> tuples = zip(*(iter(l),) *3)
        >>> labels = 'first second third'.split()
        >>> [dict(zip(labels , t)) for t in tuples][/color][/color][/color]
        [{'second': 2, 'third': 3, 'first': 1}, {'second': 5, 'third': 6, 'first': 4}]

        Basically, you can make a dict with whatever labels you want by zipping your
        labels with the appropriate tuples and calling the dict builtin.

        Steve

        Comment

        • Scott David Daniels

          #5
          Re: Packing list elements into tuples

          I kind of like:
          [dict(first=lst[k], second=lst[k+1], third=lst[k+2])
          for k in range(0, len(lst), 3)]

          --Scott David Daniels
          Scott.Daniels@A cm.Org

          Comment

          • Thorsten Kampe

            #6
            Re: Packing list elements into tuples

            * Nickolay Kolev (2004-11-09 22:29 +0100)[color=blue]
            > I have a list whose length is a multiple of 3. I want to get a list of
            > tuples each of which has 3 consecutive elements from the original list,
            > thus packing the list into smaller packets. Like this:
            >
            > l = [1,2,3,4,5,6]
            >
            > tups = [(1,2,3), (4,5,6)]
            >
            > or
            >
            > l = [1,2,3,4,5,6,7,8 ,9]
            >
            > tups = [(1,2,3), (4,5,6), (7,8,9)][/color]

            Fragment[1] from a general purpose partitioning utility:

            def part(seq, slice):
            """ partition seq """
            return [seq[slice * index:slice * (index + 1)]
            for index in range(len(seq) / slice + bool(len(seq) % slice))]

            [color=blue]
            > if i can dictionaries it would be even better:
            >
            > l = [1,2,3,4,5,6]
            >
            > tups = [
            > {'first':1,'sec ond':2,'third': 3},
            > {'first':4,'sec ond':5,'third': 6}
            > ][/color]

            You're losing order and therfore you're attaching 'first', 'second'
            and so on because you obviously need the original order. So don't use
            a dictionary.


            Thorsten

            [1] Just for the record:
            def part(seq, slice = None, modus = None):
            """
            partition seq
            syntax:
            part(seq, boolean_functio n, modus = 'bool')
            -> [[first_true_item s], [first_false_ite m, remaining_items]]
            part('str', 'separator', modus = 'sep') or
            part('str', ['separators'], modus = 'sep')
            part(list, item, modus = 'sep')
            part(n, modus = 'set')
            -> len([all_possible_pa rtitions_of_[0, 1, ..., n]])
            part(list, modus = 'set'
            -> [all_possible_pa rtitions_of_lis t]
            part(seq, int, modus = 'size')
            -> [seq0, seq1, ..., seqn] - where len(seq(i)) = int
            part(seq, [n0, n1, ..., n(i)], modus = 'size'
            -> [seq0, seq1, ..., seq(i)] - where len(seq(i)) = n(i)
            """

            Comment

            • Peter Otten

              #7
              Re: Packing list elements into tuples

              Nickolay Kolev wrote:
              [color=blue]
              > I have a list whose length is a multiple of 3. I want to get a list  of
              > tuples each of which has 3 consecutive elements from the original list,
              > thus packing the list into smaller packets. Like this:[/color]
              [color=blue]
              > ... dictionaries ... would be even better:[/color]
              [color=blue]
              > l = [1,2,3,4,5,6]
              >
              > tups = [
              > {'first':1,'sec ond':2,'third': 3},
              > {'first':4,'sec ond':5,'third': 6}
              > ][/color]

              itertools to the rescue:
              [color=blue][color=green][color=darkred]
              >>> from itertools import *
              >>> names = "first second third".split()
              >>> items = range(6)
              >>> map(dict, takewhile(bool, starmap(zip, repeat((names, iter(items))))) )[/color][/color][/color]
              [{'second': 1, 'third': 2, 'first': 0}, {'second': 4, 'third': 5, 'first':
              3}]

              Fun, but not recommended. There must be a simpler expression where you need
              not mention len(names) explicitly - but right now I can't think of one.
              Note how the nonzero len(items) % len(names) case is handled:
              [color=blue][color=green][color=darkred]
              >>> map(dict, takewhile(bool, starmap(zip, repeat((names,[/color][/color][/color]
              iter(range(5))) ))))
              [{'second': 1, 'third': 2, 'first': 0}, {'second': 4, 'first': 3}]

              However, in real life I would rather go with Steven Bethard's two-step
              approach...

              Peter




              Comment

              • Russell Blau

                #8
                Re: Packing list elements into tuples

                "Nickolay Kolev" <nmkolev@uni-bonn.de> wrote in message
                news:cmreif$rve $1@f1node01.rhr z.uni-bonn.de...[color=blue]
                > Nickolay Kolev wrote:
                >
                > I found it in the cookbook:
                > http://aspn.activestate.com/ASPN/Coo.../Recipe/303060
                >
                > It looks quite cryptic, could anyone give me some pointers at what
                > exactly is going on in the function?[/color]

                The function contains only one significant line, which is:

                return zip(*[lst[i::n] for i in range(n)])

                To figure out what it is doing, take it one piece at a time. Start with a
                list:
                [color=blue][color=green][color=darkred]
                >>> lst[/color][/color][/color]
                [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

                Pick how many elements you want in each group:
                [color=blue][color=green][color=darkred]
                >>> n=3[/color][/color][/color]

                Now see what the list comprehension does:
                [color=blue][color=green][color=darkred]
                >>> [lst[i::n] for i in range(n)][/color][/color][/color]
                [[1, 4, 7, 10], [2, 5, 8, 11], [3, 6, 9, 12]]

                So this breaks up the list into three separate lists by taking each n'th
                element from the original list, then combines them. The "n" in lst[i::n]
                determines how many elements will be skipped in creating each sub-list.
                Unfortunately, this syntax isn't mentioned in the tutorial or the library
                reference; you have to dig to find an explanation of it in


                Let's store the result of the last step so we can see what the following
                step does:
                [color=blue][color=green][color=darkred]
                >>> m = [lst[i::n] for i in range(n)]
                >>> zip(*m)[/color][/color][/color]
                [(1, 2, 3), (4, 5, 6), (7, 8, 9), (10, 11, 12)]

                The magic function zip() takes a list of sequences as its argument, and
                returns a new list that rearranges them. Imagine the first list (m) as a
                two-dimensional table in which each sub-sequence is a row; zip() goes
                through the table and returns the columns as the sub-sequences. See
                http://www.python.org/doc/2.3.4/lib/built-in-funcs.html (all the way at the
                end).


                --
                I don't actually read my hotmail account, but you can replace hotmail with
                excite if you really want to reach me.



                Comment

                • Steven Bethard

                  #9
                  Re: Packing list elements into tuples

                  On Wed, 10 Nov 2004 19:00:52 +0800, Deepak Sarda <deepak.sarda@g mail.com> wrote:[color=blue]
                  >[color=green][color=darkred]
                  > > >>> l = [1,2,3,4,5,6]
                  > > >>> zip(*(iter(l),) *3)[/color]
                  > > [(1, 2, 3), (4, 5, 6)][color=darkred]
                  > > >>> l = [1,2,3,4,5,6,7,8 ,9]
                  > > >>> zip(*(iter(l),) *3)[/color]
                  > > [(1, 2, 3), (4, 5, 6), (7, 8, 9)][/color]
                  >
                  > Can someone explain how this works?!
                  >[/color]
                  [snip][color=blue]
                  >
                  > So zip() basically gets zip(iter(l), iter(l), iter(l)) , right?[/color]

                  Close, but note that zip(iter(l), iter(l), iter(l)) creates three
                  iterators to the list l, while zip(*(iter(l),) *3) uses the same
                  iterator at each position in the tuple.
                  [color=blue][color=green][color=darkred]
                  >>> l = [1,2,3,4,5,6]
                  >>> zip(iter(l), iter(l), iter(l))[/color][/color][/color]
                  [(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5), (6, 6, 6)][color=blue][color=green][color=darkred]
                  >>> itr = iter(l)
                  >>> zip(itr, itr, itr)[/color][/color][/color]
                  [(1, 2, 3), (4, 5, 6)]

                  Here's basically what zip ends up doing when you give it 3 names bound
                  to the same iterator:
                  [color=blue][color=green][color=darkred]
                  >>> itr = iter(l)
                  >>> tuple1 = (itr.next(), itr.next(), itr.next())
                  >>> tuple1[/color][/color][/color]
                  (1, 2, 3)[color=blue][color=green][color=darkred]
                  >>> tuple2 = (itr.next(), itr.next(), itr.next())
                  >>> tuple2[/color][/color][/color]
                  (4, 5, 6)[color=blue][color=green][color=darkred]
                  >>> result = [tuple1, tuple2]
                  >>> result[/color][/color][/color]
                  [(1, 2, 3), (4, 5, 6)]

                  Note that when they're not the same iterator, zip does something like:
                  [color=blue][color=green][color=darkred]
                  >>> itr1, itr2, itr3 = iter(l), iter(l), iter(l)
                  >>> tuple1 = (itr1.next(), itr2.next(), itr3.next())
                  >>> tuple1[/color][/color][/color]
                  (1, 1, 1)[color=blue][color=green][color=darkred]
                  >>> tuple2 = (itr1.next(), itr2.next(), itr3.next())
                  >>> tuple2[/color][/color][/color]
                  (2, 2, 2)
                  ....

                  So you just get 3 copies of the elements at each index in your list.

                  Hope that helped!

                  Steve
                  --
                  You can wordify anything if you just verb it.
                  - Bucky Katt, Get Fuzzy

                  Comment

                  Working...