is there any simple way to divide this list into two separate lists , such that
L1 = [a1, a2... an]
L2=[b1,b2 ... bn]
i do not want to use loop, any methods to make this done?
One easy way is to use list comprehensions. Technically that'll
involve a loop, but the loop is handled efficiently under the hood.
L1 = [x[0] for x in L]
L2 = [x[1] for x in L]
Another way would be to construct a dictionary from your list of
tuples and then use the keys() and values() of that dictionary to form
your lists (use collections.OrderedDict if the order matters). But I
think the list comps are the best way.
ChrisA
>>> L = [('a1', 'b1'), ('a2', 'b2'),('an', 'bn')]
>>> zip(*L)
[('a1', 'a2', 'an'), ('b1', 'b2', 'bn')]
Emile
> if a list L is composed with tuple consists of two elements, that is
> L = [(a1, b1), (a2, b2) ... (an, bn)]
>
> is there any simple way to divide this list into two separate lists , such that
> L1 = [a1, a2... an]
> L2=[b1,b2 ... bn]
How about this?
>>> L = [("a1", "b1"), ("a2", "b2"), ("an", "bn")]
>>> L1, L2 = zip(*L)
>>> L1
('a1', 'a2', 'an')
>>> L2
('b1', 'b2', 'bn')
http://docs.python.org/library/functions.html#zip
-[]z.
(x,y) = [ [z[i] for z in L] for i in range(len(L[0]))]
x
: ['a1', 'a2', 'an']
y
: ['b1', 'b2', 'bn']
Nice. :) I forgot about zip, still learning Python myself.
I'll have to check up on the *L - is that a reference?
I know in Perl, you can assign the lhs to a list,
below works because there are exactly 2 items on the rhs.
Does Python have a catchall, or an ignore the rest?
Example, if L was a tuple that had 3 or more items,
the below lhs would fail. Is this possible in Python?
(X,Y) = zip(*L)
X
: ('a1', 'a2', 'an')
Y
: ('b1', 'b2', 'bn')
It expands the list into the arguments. It's the parallel to:
def func(*args):
which collapses the args into a list.
ChrisA
x,y = unzip(*L)
Not quite. That makes L1 & L2 tuples.
L1, L2 = zip(*L)
L1 = list(L1)
L2 = list(L2)
???
> Asuming you [Bud] are not an alias of Jack Smith and assuming you did
> not see Jack's thread asking the same question:
That's a strange thing to say when Bud *answered* Jack's question.
> x,y = unzip(*L)
What's unzip? It doesn't exist in any version of Python between 1.5 and 3.3
that I have.
--
Steven
> I'll have to check up on the *L - is that a reference?
No, as Chris already answered, unary * is used for packing and unpacking
positional arguments to functions; unary ** is similarly used for
collecting keyword arguments.
> I know in Perl, you can assign the lhs to a list,
> below works because there are exactly 2 items on the rhs.
> Does Python have a catchall, or an ignore the rest?
Yes. In Python 3, you can do this:
>>> a, b, *t, c = (1, 2, 3, 4, 5, 6, 7, 8, 9)
>>> t
[3, 4, 5, 6, 7, 8]
(but not in Python 2)
--
Steven
> On Sat, Aug 6, 2011 at 6:07 PM, smith jack <thin...@gmail.com> wrote:
>> if a list L is composed with tuple consists of two elements, that is
>> L = [(a1, b1), (a2, b2) ... (an, bn)]
>>
>> is there any simple way to divide this list into two separate lists ,
>> such that L1 = [a1, a2... an]
>> L2=[b1,b2 ... bn]
>>
>> i do not want to use loop, any methods to make this done?
>
> One easy way is to use list comprehensions. Technically that'll
> involve a loop, but the loop is handled efficiently under the hood.
>
> L1 = [x[0] for x in L]
> L2 = [x[1] for x in L]
I hardly think that's "under the hood". It's right there: for x in L. How
much more explicitly a loop do you want?
To the original poster, Jack: if you don't loop over the list, how do you
expect to operate on each and every item?
Whether you write:
L1, L2 = [], []
for a,b in L:
L1.append(a)
L2.append(b)
or
L1, L2 = zip(*L)
or
L1 = [x[0] for x in L]
L2 = [x[1] for x in L]
you are still looping over the list. In the second case, the one-liner using
zip, you loop *twice*: once to unpack L into separate arguments, the second
time to zip them up. And the result you end up with are tuples, not lists,
so if you need lists, you have to loop *again*, over each tuple, converting
them to lists. Here's one way to do that while keeping it a one-liner:
L1, L2 = map(list, zip(*L))
If L is small, it really doesn't matter what you do, they will all be more
or less as efficient. Write whatever you feel looks best.
But if L is huge, then the difference between a four-liner that iterates
over the list once, and one-liner that iterates over it four times, may be
considerable.
--
Steven
There will always be a loop. It might not be written with a "for"
statement, but there will always be a loop.
L1 = [k[0] for k in L]
L2 = [k[1] for k in L]
I did momentarily consider the following slimy solution:
L1 = dict(L).keys()
L2 = dict(L).values()
but that reorders the tuples. They still correspond, but in a different
order.
--
Tim Roberts, ti...@probo.com
Providenza & Boekelheide, Inc.
Which can be overcome with collections.OrderedDict. But what's dict(L)
going to do? It's going to loop over L, more than once in fact.
I guess the real question is: Why do you wish to avoid a loop?
ChrisA
I think what the Original Poster actually meant was he wanted to avoid
*writing out an explicit loop*. That is, he wants a one-liner, so he
doesn't have to think about the details of iterating over the list.
When we write:
a = sum(a_sequence)
aren't we doing the same thing really?
--
Steven
That is called unzipping and there is a sneaky idiom for it:
L1,L2 = zip(*L)
Your homework assignment is figuring out how that works ;-).
L1, L2 = map(list, zip(*L))
--
By ZeD
Arg typo:
I meant of course zip
>
>