Zip พร้อมเอาต์พุตรายการแทนทูเปิล


94

วิธีที่รวดเร็วและสวยงามที่สุดในการทำรายการจากสองรายการคืออะไร

ฉันมี

In [1]: a=[1,2,3,4,5,6]

In [2]: b=[7,8,9,10,11,12]

In [3]: zip(a,b)
Out[3]: [(1, 7), (2, 8), (3, 9), (4, 10), (5, 11), (6, 12)]

และฉันอยากจะมี

In [3]: some_method(a,b)
Out[3]: [[1, 7], [2, 8], [3, 9], [4, 10], [5, 11], [6, 12]]

ฉันกำลังคิดเกี่ยวกับการใช้แผนที่แทน zip แต่ฉันไม่รู้ว่ามีวิธีการไลบรารีมาตรฐานที่จะใช้เป็นอาร์กิวเมนต์แรกหรือไม่

ฉันสามารถกำหนดฟังก์ชั่นของตัวเองสำหรับสิ่งนี้และใช้แผนที่คำถามของฉันคือถ้ามีการใช้งานบางอย่างแล้ว ยังไม่มีคำตอบ


1
คุณต้องการรายการจริงๆหรือ? คุณจะทำอย่างไรกับผลลัพธ์?
Karl Knechtel

14
ตัวอย่างจะเป็นแบบ sklearn ซึ่งหลาย ๆ ครั้งข้อมูลจะต้องถูกจัดระเบียบในลักษณะนี้
tumultous_rooster

คำตอบ:


101

หากคุณกำลังซิปมากกว่า 2 รายการ (หรือมีเพียง 2 รายการสำหรับเรื่องนั้น) วิธีที่อ่านได้คือ:

[list(a) for a in zip([1,2,3], [4,5,6], [7,8,9])]

สิ่งนี้ใช้การทำความเข้าใจรายการและแปลงแต่ละองค์ประกอบในรายการ (ทูเปิล) เป็นรายการ


54

คุณเกือบจะได้คำตอบด้วยตัวคุณเอง อย่าใช้mapแทนzip. ใช้map AND zip .

คุณสามารถใช้แผนที่ร่วมกับซิปเพื่อความหรูหราและใช้งานได้:

list(map(list, zip(a, b)))

zipส่งคืนรายการสิ่งที่เพิ่มขึ้น map(list, [...])เรียกlistทูเพิลแต่ละตัวในรายการ list(map([...])เปลี่ยนวัตถุแผนที่ให้เป็นรายการที่อ่านได้


การตัดสินใจที่โชคร้ายในการดำเนินการคอลเลกชัน python 3 ส่งคืนgeneratorค่าใช้จ่ายของสองเท่าlistที่นี่
StephenBoesch

15

ฉันชอบความสง่างามของฟังก์ชัน zip แต่การใช้ฟังก์ชัน itemgetter () ในโมดูลตัวดำเนินการดูเหมือนจะเร็วกว่ามาก ฉันเขียนสคริปต์ง่ายๆเพื่อทดสอบสิ่งนี้:

import time
from operator import itemgetter

list1 = list()
list2 = list()
origlist = list()
for i in range (1,5000000):
        t = (i, 2*i)
        origlist.append(t)

print "Using zip"
starttime = time.time()
list1, list2 = map(list, zip(*origlist))
elapsed = time.time()-starttime
print elapsed

print "Using itemgetter"
starttime = time.time()
list1 = map(itemgetter(0),origlist)
list2 = map(itemgetter(1),origlist)
elapsed = time.time()-starttime
print elapsed

ฉันคาดว่า zip จะเร็วกว่า แต่วิธีการรับไอเทมจะชนะด้วยการยิงไกล:

Using zip
6.1550450325
Using itemgetter
0.768098831177

2
นี่เป็นการเปลี่ยนสิ่งที่ OP พยายามทำ คุณช่วยอัปเดตโพสต์ให้สอดคล้องกับสิ่งนั้นได้ไหม กล่าวคือ OP กำลังแปลงสองรายการเป็นรายการหรือจำนวนคู่โดยพลการ คุณกำลังแปลงจำนวนคู่โดยพลการเป็นคู่ของรายการ
Mad Physicist

Python รุ่นนี้วัดด้วยรุ่นใด
Moberg

ฉันจำไม่ได้ว่าเมื่อสองปีก่อน แต่น่าจะเป็น 2.6 หรือ 2.7 ฉันคิดว่าคุณสามารถคัดลอกโค้ดและลองใช้กับเวอร์ชัน / แพลตฟอร์มของคุณเองได้
kslnet

2
python 2 zipสร้างรายการจริง ทำให้สิ่งต่างๆช้าลง ลองแทนที่zipด้วยitertools.izipแล้ว
Jean-François Fabre

ใน Python 3.5 zip จะใช้เวลา 3.5 วินาทีและ itemgetter ใช้เวลา 0.10 วินาที สำหรับผู้ที่รัก comprehensions รายการงานก็เช่นเดียวกับlist1 = [x[0] for x in origlist] list1 = map(itemgetter(0), origlist)
Elias Strehle

3

โดยทั่วไปฉันไม่ชอบใช้แลมด้า แต่ ...

>>> a = [1, 2, 3, 4, 5]
>>> b = [6, 7, 8, 9, 10]
>>> c = lambda a, b: [list(c) for c in zip(a, b)]
>>> c(a, b)
[[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]

หากคุณต้องการความเร็วพิเศษแผนที่จะเร็วขึ้นเล็กน้อย:

>>> d = lambda a, b: map(list, zip(a, b))
>>> d(a, b)
[[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]

อย่างไรก็ตามแผนที่ถือว่าไม่เป็นความลับและควรใช้สำหรับการปรับแต่งประสิทธิภาพเท่านั้น


4
อะไรlambdaเพิ่มที่นี่? เราสามารถเขียนนิพจน์แทนการเรียกใช้ฟังก์ชัน (มันไม่ซับซ้อนจริงๆ) และแม้ว่าใครจะต้องการฟังก์ชันก็สามารถกำหนดได้อย่างไม่ลำบากในสองบรรทัด (ถ้าคีย์ย้อนกลับของคุณเสียหรือคุณเสียสติ) . mapในทางกลับกันนั้นดีมากถ้าอาร์กิวเมนต์แรกเป็นฟังก์ชันธรรมดา (ตรงข้ามกับ a lambda)

1
เขาขอฟังก์ชั่น แต่ฉันเห็นด้วย - อาจจะดีกว่าแค่จ่ายเงินเพิ่ม สำหรับแผนที่ฉันเชื่อว่าความเข้าใจในรายการมักจะชัดเจนกว่าเสมอ
Ceasar Bautista

1
ฉันจะแนะนำมากกว่าmap ดังนั้นlambda map(list, zip(a,b))ความเข้าใจในรายการอาจชัดเจนขึ้นเล็กน้อย แต่แผนที่ควรเร็วกว่านี้ (ยังไม่ทดลอง)
inspectorG4dget

ฉันหมายถึงอีกครั้งถ้า OP ต้องการความเร็วแผนที่คือทางไป แต่โดยทั่วไปและโดยเฉพาะใน Python ให้เน้นความสามารถในการอ่านมากกว่าความเร็ว (มิฉะนั้นคุณจะเข้าสู่การเพิ่มประสิทธิภาพก่อนเวลาอันควร)
Ceasar Bautista

3

แล้วเรื่องนี้ล่ะ?

>>> def list_(*args): return list(args)

>>> map(list_, range(5), range(9,4,-1))
[[0, 9], [1, 8], [2, 7], [3, 6], [4, 5]]

หรือดีกว่า:

>>> def zip_(*args): return map(list_, *args)
>>> zip_(range(5), range(9,4,-1))
[[0, 9], [1, 8], [2, 7], [3, 6], [4, 5]]

ดูเหมือนว่าสำหรับฉันจะเป็นคำตอบที่ดีกว่าส่วนที่เหลือเนื่องจากที่นี่เรากำลังลดขั้นตอนหนึ่งโดยไม่ทำการ zip และสร้างรายการโดยตรง Awesome
Akshay Hazari

2

ใช้ numpy

ความหมายของความสง่างามที่สามารถเป็นที่น่าสงสัยมาก แต่ถ้าคุณกำลังทำงานกับnumpyการสร้างอาร์เรย์และการแปลงไปยังรายการ (ถ้าจำเป็น ... ) อาจจะเป็นในทางปฏิบัติแม้ไม่ได้มีประสิทธิภาพดังนั้นมากเมื่อเทียบกับการใช้mapฟังก์ชั่นหรือความเข้าใจในรายการ

import numpy as np 
a = b = range(10)
zipped = zip(a,b)
result = np.array(zipped).tolist()
Out: [[0, 0],
 [1, 1],
 [2, 2],
 [3, 3],
 [4, 4],
 [5, 5],
 [6, 6],
 [7, 7],
 [8, 8],
 [9, 9]]

มิฉะนั้นจะข้ามzipฟังก์ชันที่คุณสามารถใช้ได้โดยตรงnp.dstack:

np.dstack((a,b))[0].tolist()

1

ความเข้าใจในรายการจะเป็นวิธีแก้ปัญหาที่ง่ายมาก

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

b=[7,8,9,10,11,12]

x = [[i, j] for i, j in zip(a,b)]

print(x)

output : [[1, 7], [2, 8], [3, 9], [4, 10], [5, 11], [6, 12]]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.