2016-03-04 13 views
7

Làm thế nào để lặp qua 2 danh sách của tôi để tôi có thể sử dụngTạo danh sách mới bằng cách lấy mục đầu tiên trong danh sách đầu tiên, và mục cuối cùng trong danh sách thứ hai

a=[1,2,3,8,12] 
b=[2,6,4,5,6] 

để có được

[1,6,2,5,3,8,6,12,2] 

HOẶC sử dụng

d=[a,b,c,d] 
e=[w,x,y,z] 

để có được

.210

(yếu tố 1 từ danh sách 1, yếu tố cuối cùng trong danh sách 2)
(yếu tố thứ 2 trong danh sách 1, 2 đến yếu tố cuối cùng trong danh sách 2)

+0

Phần nào bạn gặp khó khăn với? –

Trả lời

11
[value for pair in zip(a, b[::-1]) for value in pair] 
5

Bạn có thể zip danh sách đầu tiên với sự đảo ngược của một giây (sử dụng itertools.izip_longest) sau đó tham gia các cột bằng itertools.chain:

>>> d=['a','b','c','d'] 
>>> e=['w','x','y','z'] 
>>> 
>>> from itertools import chain, zip_longest # in python 2 use izip_longest 
>>> 
>>> list(chain(*izip_longest(d, e[::-1]))) 
['a', 'z', 'b', 'y', 'c', 'x', 'd', 'w'] 

Ưu điểm của việc sử dụng zip_longest() là nó có một đối số fillvalue đó sẽ được thông qua để điền vào các mục bỏ qua khi chiều dài của danh sách của bạn không bằng nhau.

Nếu bạn chắc chắn rằng độ dài của danh sách bằng nhau thì tốt hơn bạn nên sử dụng hàm dựng sẵn zip().

>>> d=['a','b'] 
>>> e=['w','x','y','z'] 
>>> list(chain(*izip_longest(d, e[::-1], fillvalue=''))) 
['a', 'z', 'b', 'y', '', 'x', '', 'w'] 

More cách pythonic đề xuất bởi @ Jon Clements:

list(chain.from_iterable(zip_longest(d, reversed(e)))) 
+0

Nó được coi là hình thức tốt hơn để sử dụng 'chain.from_iterable (iterable)' thay vì 'chain (* iterable)' ... và nếu bạn muốn tránh tạo một danh sách mới, thay vì 'e [:: - 1]' bạn có thể sử dụng 'đảo ngược (e)' để tất cả trong tất cả: 'list (chain.from_iterable (zip_longest (d, reversed (e)))) ' –

+0

Có lẽ phương pháp tôi sử dụng là lấy công thức' roundrobin' itertools, và cung cấp nó 'd' và' đảo ngược (e) 'làm đầu vào - sẽ xử lý các danh sách chiều dài khác nhau (không lo lắng về các giá trị điền) và sẽ mở rộng đến một số lượng tùy ý của các vòng lặp như đầu vào –

+0

@JonClements Có, sử dụng 'reverse()' là một ý tưởng tốt hơn nhưng tôi nghĩ sử dụng 'roundrobin' (mặc dù là cách pythonic) là quá mức cần thiết trong trường hợp này. – Kasramvd

0

Vâng, tôi đã thực hiện một số xét nghiệm cho python2:

import time 
from operator import itemgetter 
from itertools import chain, izip_longest 

a = [1, 2, 3, 8, 12] 
b = [2, 6, 4, 5, 6] 

print "Using value and zip" 
starttime = time.time() 
c = [value for pair in zip(a, b[::-1]) for value in pair] 
elapsed = time.time() - starttime 
print c 
print elapsed 

print "Using chain and izip" 
starttime = time.time() 
c = list(chain(*izip_longest(a, b[::-1]))) 
elapsed = time.time() - starttime 
print c 
print elapsed 

print "Using itemgetter" 
c = [] 
starttime = time.time() 
for i in xrange(0, len(a)): 
    c.append(itemgetter(i)(a)) 
    c.append(itemgetter(len(b)-i-1)(b)) 
elapsed = time.time() - starttime 
print c 
print elapsed 

đầu ra:

Using value and zip 
[1, 6, 2, 5, 3, 4, 8, 6, 12, 2] 
1.59740447998e-05 
Using chain and izip 
[1, 6, 2, 5, 3, 4, 8, 6, 12, 2] 
3.2901763916e-05 
Using itemgetter 
[1, 6, 2, 5, 3, 4, 8, 6, 12, 2] 
1.4066696167e-05 

Đôi khi phương pháp đầu tiên nhanh hơn và đôi khi là phương pháp thứ ba.

Đó là những kết quả cho các danh sách chiều dài = 1000:

Using value and zip 
0.000767946243286 
Using chain and izip 
0.000431060791016 
Using itemgetter 
0.00203609466553 

Như Bạn có thể xem phương pháp thứ hai được tốt hơn cho danh sách dài hơn.

0

Làm thế nào về điều này:

a=[1,2,3,8,12] 
b=[2,6,4,5,6] 
>>> a1 = list(map(lambda x: a1.extend([x,0]), a)) 
[None, None, None, None, None] 
>>> a1 
[1, 0, 2, 0, 3, 0, 8, 0, 12, 0] 
>>> b1 = list(map(lambda x: b1.extend([0,x]), b[::-1])) 
[None, None, None, None, None] 
>>> b1 
[0, 6, 0, 5, 0, 4, 0, 6, 0, 2] 
>>> c = [x+y for x,y in zip(a1,b1)] 
>>> c 
[1, 6, 2, 5, 3, 4, 8, 6, 12, 2] 

Nếu a và b là với độ dài khác nhau, sau đó:

>>> c = [x+y for x,y in izip_longest(a1,b1)] #you choose your fillvalue. 
Các vấn đề liên quan