40

I have

a = [1, 2]
b = ['a', 'b']

I want

c = [1, 'a', 2, 'b']
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
sureshvv
  • 4,234
  • 1
  • 26
  • 32
  • 1
    @cdleary's answer http://stackoverflow.com/questions/406121/flattening-a-shallow-list-in-python/408281#408281 provides performance comparison for various ways of "Flattening a shallow list in python" (flattening `zip(a,b)` gives you the answer). – jfs Aug 12 '10 at 21:26

9 Answers9

75
[j for i in zip(a,b) for j in i]
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
30

If the order of the elements much match the order in your example then you can use a combination of zip and chain:

from itertools import chain
c = list(chain(*zip(a,b)))

If you don't care about the order of the elements in your result then there's a simpler way:

c = a + b
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • 1
    using this in my case: 'c = a+b' -- > lists are not iterable. What then? Only chain works check my question to understand my problem: 'http://stackoverflow.com/questions/40952892/extract-url-their-names-of-an-html-file-stored-on-disk-and-print-them-respecti' – Yannis Dran Dec 04 '16 at 11:29
  • for index, row in datas.iterrows(): textF = re.findall('{{f}}(.*?)}}', row['review']) matrixF += textF if index==3: break for index in matrixF: print index , it's still works, so it's still iterable i think ? ._. – Budi Mulyo Sep 07 '17 at 04:20
  • 1
    There is [chain.from_iterable](https://docs.python.org/3/library/itertools.html#itertools.chain.from_iterable): `list(chain.from_iterable(zip(a, b)))` -- perfectly lazy way to do this. – byashimov Jan 17 '18 at 15:58
24

Parsing

[item for pair in zip(a, b) for item in pair]

in your head is easy enough if you recall that the for and if clauses are done in order, followed a final append of the result:

temp = []
for pair in zip(a, b):
    for item in pair :
        temp.append(item )
Neuron
  • 5,141
  • 5
  • 38
  • 59
John Machin
  • 81,303
  • 11
  • 141
  • 189
  • I'm normally very comfortable with LEs, but this double looping got me all confused. Thanks for the nice explanation. – Jeffrey Jose Aug 14 '10 at 08:18
5

An alternate method using index slicing which turns out to be faster and scales better than zip:

def slicezip(a, b):
    result = [0]*(len(a)+len(b))
    result[::2] = a
    result[1::2] = b
    return result

You'll notice that this only works if len(a) == len(b) but putting conditions to emulate zip will not scale with a or b.

For comparison:

a = range(100)
b = range(100)

%timeit [j for i in zip(a,b) for j in i]
100000 loops, best of 3: 15.4 µs per loop

%timeit list(chain(*zip(a,b)))
100000 loops, best of 3: 11.9 µs per loop

%timeit slicezip(a,b)
100000 loops, best of 3: 2.76 µs per loop
SeanM
  • 51
  • 1
  • 3
  • what do you mean by "putting conditions to emulate zip will not scale with a or b"? – sureshvv Sep 25 '14 at 07:36
  • I simply meant that with zip, if one list is longer than the other, the longer list gets truncated to merge it with the shorter list. One could do this by comparing the lengths of each array and then only assigning a shortened version of the longer one. This checking of lengths and truncation does not take any longer if the arrays get bigger. – SeanM Sep 26 '14 at 08:40
  • Note: This works well for bisecting purposes that favor the first list: it tolerates being the same length or one longer than the second `slicezip([1,2,3],[4,5])`, which means you don't have to handle uneven lists in that case (which is very nice) – TemporalWolf Feb 14 '17 at 20:44
4

If you care about order:

#import operator
import itertools
a = [1,2]
b = ['a','b']
#c = list(reduce(operator.add,zip(a,b))) # slow.
c = list(itertools.chain.from_iterable(zip(a,b))) # better.

print c gives [1, 'a', 2, 'b']

Nick T
  • 25,754
  • 12
  • 83
  • 121
3

Simple.. please follow this pattern.

x = [1 , 2 , 3]
y = ["a" , "b" , "c"]

z =list(zip(x,y))
print(z)
0
def main():

drinks = ["Johnnie Walker", "Jose Cuervo", "Jim Beam", "Jack Daniels,"]
booze = [1, 2, 3, 4, 5]
num_drinks = []
x = 0
for i in booze:

    if x < len(drinks):

        num_drinks.append(drinks[x])
        num_drinks.append(booze[x])

        x += 1

    else:

        print(num_drinks)

return

main()

0

Here is a standard / self-explaining solution, i hope someone will find it useful:

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

c = []
for x, y in zip(a, b):
    c.append(x)
    c.append(y)

print (c)

output:

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

Of course, you can change it and do manipulations on the values if needed

Samer Aamar
  • 1,298
  • 1
  • 15
  • 23
-3
c = []
c.extend(a)
c.extend(b)
Donald Duck
  • 8,409
  • 22
  • 75
  • 99
  • 2
    The desired result is entirely different. – vaultah Sep 06 '17 at 12:44
  • 1
    While this code may answer the question, providing additional context regarding how and/or why it solves the problem would improve the answer's long-term value. – Donald Duck Sep 06 '17 at 15:44
  • if it answers the question and is different from all other answers, why not support it? i believe there's not much context to the quesetion so any relevant answers are welcome. – Arvind S.P Sep 07 '17 at 04:46