467,083 Members | 1,255 Online
Bytes | Developer Community
Ask Question

Home New Posts Topics Members FAQ

Post your question to a community of 467,083 developers. It's quick & easy.

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,'second':2,'third':3},
{'first':4,'second':5,'third':6}
]

and so on.

Any ideas?

Many thanks in advance!

Cheers,
-- Nickolay
Jul 18 '05 #1
  • viewed: 2438
Share:
8 Replies
"Nickolay Kolev" <nm*****@uni-bonn.de> wrote in message
news:cm**********@f1node01.rhrz.uni-bonn.de...
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)]
How's this? :
alist [1, 2, 3, 4, 5, 6, 7, 8, 9] tups = [tuple(alist[i:i+3]) for i in xrange(0, len(alist), 3)]
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,'second':2,'third':3},
{'first':4,'second':5,'third':6}
]


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.
Jul 18 '05 #2
Nickolay Kolev wrote:
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:


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?

Cheers,
-- Nickolay
Jul 18 '05 #3
Nickolay Kolev <nmkolev <at> uni-bonn.de> writes:
l = [1,2,3,4,5,6]

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


My favorite idiom:
l = [1,2,3,4,5,6]
zip(*(iter(l),)*3) [(1, 2, 3), (4, 5, 6)] l = [1,2,3,4,5,6,7,8,9]
zip(*(iter(l),)*3) [(1, 2, 3), (4, 5, 6), (7, 8, 9)]

If you want dicts, try:
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]

[{'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

Jul 18 '05 #4
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
Sc***********@Acm.Org
Jul 18 '05 #5
* Nickolay Kolev (2004-11-09 22:29 +0100)
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)]
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))]

if i can dictionaries it would be even better:

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

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


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_function, modus = 'bool')
-> [[first_true_items], [first_false_item, 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_partitions_of_[0, 1, ..., n]])
part(list, modus = 'set'
-> [all_possible_partitions_of_list]
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)
"""
Jul 18 '05 #6
Nickolay Kolev wrote:
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: ... dictionaries ... would be even better: l = [1,2,3,4,5,6]

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


itertools to the rescue:
from itertools import *
names = "first second third".split()
items = range(6)
map(dict, takewhile(bool, starmap(zip, repeat((names, iter(items)))))) [{'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:
map(dict, takewhile(bool, starmap(zip, repeat((names,

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


Jul 18 '05 #7
"Nickolay Kolev" <nm*****@uni-bonn.de> wrote in message
news:cm**********@f1node01.rhrz.uni-bonn.de...
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?


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:
lst [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

Pick how many elements you want in each group:
n=3
Now see what the list comprehension does:
[lst[i::n] for i in range(n)] [[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
http://www.python.org/doc/2.3.4/what...on-slices.html

Let's store the result of the last step so we can see what the following
step does:
m = [lst[i::n] for i in range(n)]
zip(*m)

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

Jul 18 '05 #8
On Wed, 10 Nov 2004 19:00:52 +0800, Deepak Sarda <de**********@gmail.com> wrote:
>> l = [1,2,3,4,5,6]
>> zip(*(iter(l),)*3) [(1, 2, 3), (4, 5, 6)]
>> l = [1,2,3,4,5,6,7,8,9]
>> zip(*(iter(l),)*3)

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


Can someone explain how this works?!

[snip]
So zip() basically gets zip(iter(l), iter(l), iter(l)) , right?


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.
l = [1,2,3,4,5,6]
zip(iter(l), iter(l), iter(l)) [(1, 1, 1), (2, 2, 2), (3, 3, 3), (4, 4, 4), (5, 5, 5), (6, 6, 6)] itr = iter(l)
zip(itr, itr, itr) [(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:
itr = iter(l)
tuple1 = (itr.next(), itr.next(), itr.next())
tuple1 (1, 2, 3) tuple2 = (itr.next(), itr.next(), itr.next())
tuple2 (4, 5, 6) result = [tuple1, tuple2]
result [(1, 2, 3), (4, 5, 6)]

Note that when they're not the same iterator, zip does something like:
itr1, itr2, itr3 = iter(l), iter(l), iter(l)
tuple1 = (itr1.next(), itr2.next(), itr3.next())
tuple1 (1, 1, 1) tuple2 = (itr1.next(), itr2.next(), itr3.next())
tuple2

(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
Jul 18 '05 #9

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

11 posts views Thread by Nicolas Girard | last post: by
5 posts views Thread by Christian Seberino | last post: by
9 posts views Thread by Yomanium Yoth Taripoät II | last post: by
7 posts views Thread by Ben | last post: by
3 posts views Thread by Dirk Hagemann | last post: by
90 posts views Thread by Christoph Zwerschke | last post: by
43 posts views Thread by michael.f.ellis@gmail.com | last post: by
11 posts views Thread by Noah | last post: by
17 posts views Thread by John Salerno | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.