sam
sam

Reputation: 19164

Combining two lists into a list of lists

I have two lists:

a = ['1', '2']
b = ['11', '22', '33', '44']

And I to combine them to create a list like the one below:

op = [('1', '11'), ('2', '22'), ('', '33'), ('', '44')]

How could I achieve this?

Upvotes: 4

Views: 674

Answers (2)

Vidhya G
Vidhya G

Reputation: 2320

In Python 2.7: another way to do this:

[('', i[1]) if i[0] == None else i for i in map(None, a, b)]

For the example lists given in the question, this way is faster than using using izip_longest:

>>> timeit.timeit("[('', i[1]) if i[0] == None else i  for i in map(None, a, b)]", 'from __main__ import a, b')
1.3226220607757568

>>> timeit.timeit("list(itertools.izip_longest(a, b, fillvalue=''))", 'from __main__ import a, b')
1.629504919052124

If the lists are longer and the non-existing value is to be filled with '' then izip_longest is significantly faster.

However, if you are content for the resulting list to be creating with a None rather than a '', you don't need the list comprehension or the conditional: just map(None, a, b). Then the speed can be similar to that of izip_ilongest for longer lists.

Note that when lists of unequal length are to be combined it is not necessarily the case that the result should take the length of the longer one. If you want a zip type function to always take the length of the first argument then the answers to the SO question "Is there a middle ground between `zip` and `zip_longest`" are illuminating.

Upvotes: -1

Padraic Cunningham
Padraic Cunningham

Reputation: 180411

You want itertools.zip_longest with a fillvalue of an empty string:

a = ['1', '2']
b = ['11', '22', '33', '44']

from itertools import zip_longest # izip_longest for python2

print(list(zip_longest(a,b, fillvalue="")))
[('1', '11'), ('2', '22'), ('', '33'), ('', '44')]

For python2 it is izip_longest:

from itertools import izip_longest 

print(list(izip_longest(a,b, fillvalue="")))
[('1', '11'), ('2', '22'), ('', '33'), ('', '44')]

If you just want to use the values you can iterate over the the izip object:

for i,j  in izip_longest(a,b, fillvalue=""):
   # do whatever

Some timings vs using map:

In [51]: a = a * 10000

In [52]: b = b * 9000

In [53]: timeit list(izip_longest(a,b,fillvalue=""))
100 loops, best of 3: 1.91 ms per loop

In [54]: timeit [('', i[1]) if i[0] == None else i  for i in map(None, a, b)]
100 loops, best of 3: 6.98 ms per loop

map also creates another list using python2 so for large lists or if you have memory restrictions it is best avoided.

Upvotes: 9

Related Questions