แยกรายการแรกของแต่ละรายการย่อย


148

ฉันสงสัยว่าเป็นวิธีที่ดีที่สุดในการแยกรายการแรกของแต่ละรายการย่อยในรายการของรายการและผนวกเข้ากับรายการใหม่ ดังนั้นถ้าฉันมี:

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

และฉันต้องการที่จะดึงออกa, 1และxและสร้างรายการแยกต่างหากจากผู้ที่

ฉันเหนื่อย:

lst2.append(x[0] for x in lst)

1
รหัสของคุณเกือบถูกต้อง ปัญหาเดียวคือการใช้รายการความเข้าใจ
Abhishek Mittal

คำตอบ:


199

ใช้รายการเข้าใจ :

>>> lst = [['a','b','c'], [1,2,3], ['x','y','z']]
>>> lst2 = [item[0] for item in lst]
>>> lst2
['a', 1, 'x']

รายการความเข้าใจวิธียังเป็นวิธีที่เร็วที่สุดเร็วกว่าวิธี Numpy คำตอบของjboiพูดถึงการเปรียบเทียบประสิทธิภาพ
Qiao Zhang

83

คุณสามารถใช้รหัสไปรษณีย์:

>>> lst=[[1,2,3],[11,12,13],[21,22,23]]
>>> zip(*lst)[0]
(1, 11, 21)

หรือ Python 3 ที่zipไม่มีรายการ:

>>> list(zip(*lst))[0]
(1, 11, 21)

หรือ,

>>> next(zip(*lst))
(1, 11, 21)

หรือ (ฉันชอบ) ใช้ numpy:

>>> import numpy as np
>>> a=np.array([[1,2,3],[11,12,13],[21,22,23]])
>>> a
array([[ 1,  2,  3],
       [11, 12, 13],
       [21, 22, 23]])
>>> a[:,0]
array([ 1, 11, 21])

ยังไม่ได้ลงคะแนน แต่เป็นตัวอย่างข้อมูลโค้ดแรก (รหัสไปรษณีย์) ที่สร้างขึ้น: วัตถุ "'zip' ไม่สามารถถอดรหัสได้" Python 3.6 บน Jupyter
jboi

@jboi: เพียงแค่ห่อรอบแรกหรือการใช้งานlist nextขอบคุณ
dawg

20

มีปัญหาเดียวกันและอยากรู้เกี่ยวกับประสิทธิภาพของแต่ละโซลูชัน

นี่คือ%timeit:

import numpy as np
lst = [['a','b','c'], [1,2,3], ['x','y','z']]

numpy-way แรกเปลี่ยนอาร์เรย์:

%timeit list(np.array(lst).T[0])
4.9 µs ± 163 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

เนี้ยบอย่างสมบูรณ์โดยใช้รายการความเข้าใจ (ตามที่อธิบายโดย @alecxe):

%timeit [item[0] for item in lst]
379 ns ± 23.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

อีกวิธีใช้ภาษาพื้นเมืองzip(ตามที่อธิบายโดย @dawg):

%timeit list(zip(*lst))[0]
585 ns ± 7.26 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

วิธีที่สอง numpy อธิบายโดย @dawg:

%timeit list(np.array(lst)[:,0])
4.95 µs ± 179 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

น่าแปลกที่ (อย่างน้อยที่สุดสำหรับฉัน) วิธีดั้งเดิมที่ใช้ความเข้าใจในรายการเป็นวิธีที่เร็วที่สุดและเร็วขึ้นประมาณ 10 เท่าเมื่อเทียบกับ numpy-way การรันทั้งสองวิธีแบบ numpy โดยไม่ต้องlistบันทึกขั้นสุดท้ายจะช่วยประหยัดประมาณหนึ่ง ones ซึ่งยังคงอยู่ในความแตกต่าง 10x

โปรดทราบว่าเมื่อฉันล้อมรอบโค้ดขนาดสั้นแต่ละอันด้วยการเรียกเพื่อlenให้แน่ใจว่าเครื่องกำเนิดไฟฟ้าจะทำงานไปจนจบระยะเวลายังคงเหมือนเดิม


4
มีค่าใช้จ่ายมากมายเมื่อสร้างอาร์เรย์
hpaulj

1
เห็นด้วยกับ hpaulj ถ้าคุณเริ่มต้นด้วยอาร์เรย์ numpy [:, 0] เร็วขึ้น ลองไปดูกัน: lst = np.array ([['a', 'b', 'c'], [1,2,3], ['x', 'y', 'z']]), จากนั้น lst [:, 0] การแปลงในตัวอย่างเวลาการทดลองให้ความเข้าใจในรายการมีความได้เปรียบอย่างไม่เป็นธรรม ดังนั้นถ้าคุณทำได้ให้ใช้อาร์เรย์ numpy เพื่อเก็บข้อมูลของคุณหากความเร็วเป็นเป้าหมายสูงสุดของคุณ Numpy เกือบเร็วขึ้นเสมอ มันสร้างขึ้นเพื่อความเร็ว
spacedustpi

13

Python มีฟังก์ชั่นที่ชื่อว่า itemgetter เพื่อส่งคืนไอเท็มที่ดัชนีเฉพาะในรายการ:

from operator import itemgetter

ผ่าน itemgetter () ฟังก์ชั่นดัชนีของรายการที่คุณต้องการดึง เพื่อดึงไอเท็มแรกคุณจะใช้ itemgetter (0) สิ่งสำคัญที่ต้องเข้าใจคือ itemgetter (0) ส่งคืนฟังก์ชัน หากคุณส่งรายการไปยังฟังก์ชันนั้นคุณจะได้รับรายการเฉพาะ:

itemgetter(0)([10, 20, 30]) # Returns 10

สิ่งนี้มีประโยชน์เมื่อคุณรวมเข้ากับ map () ซึ่งรับฟังก์ชั่นเป็นอาร์กิวเมนต์ตัวแรกและรายการ (หรือตัวทำซ้ำอื่น ๆ ) เป็นอาร์กิวเมนต์ที่สอง มันคืนค่าผลลัพธ์ของการเรียกใช้ฟังก์ชันบนแต่ละวัตถุใน iterable:

my_list = [['a', 'b', 'c'], [1, 2, 3], ['x', 'y', 'z']]
list(map(itemgetter(0), my_list)) # Returns ['a', 1, 'x']

โปรดทราบว่า map () ส่งคืนตัวกำเนิดดังนั้นผลลัพธ์จะถูกส่งไปยัง list () เพื่อรับรายการจริง โดยสรุปงานของคุณสามารถทำได้ดังนี้:

lst2.append(list(map(itemgetter(0), lst)))

นี่เป็นวิธีทางเลือกในการใช้ list comprehension และวิธีการเลือกใดขึ้นอยู่กับบริบทความสามารถในการอ่านและการกำหนดลักษณะ

ข้อมูลเพิ่มเติม: https://docs.python.org/3/library/operator.html#operator.itemgetter


2

รหัสของคุณเกือบถูกต้อง ปัญหาเดียวคือการใช้รายการความเข้าใจ

หากคุณใช้ like: (x [0] สำหรับ x ใน lst) จะส่งคืนวัตถุตัวสร้าง หากคุณใช้ like: [x [0] สำหรับ x ใน lst] มันจะส่งคืนรายการ

เมื่อคุณผนวกเอาท์พุตความเข้าใจลิสต์เข้ากับลิสต์ผลลัพธ์ของลิสต์ความเข้าใจคือองค์ประกอบเดียวของรายการ

lst = [["a","b","c"], [1,2,3], ["x","y","z"]]
lst2 = []
lst2.append([x[0] for x in lst])
print lst2[0]

lst2 = [['a', 1, 'x']]

lst2 [0] = ['a', 1, 'x']

โปรดแจ้งให้เราทราบหากฉันไม่ถูกต้อง



0

คุณบอกว่าคุณมีรายการที่มีอยู่ ดังนั้นฉันจะไปกับที่

>>> lst1 = [['a','b','c'], [1,2,3], ['x','y','z']]
>>> lst2 = [1, 2, 3]

ตอนนี้คุณกำลังผนวกวัตถุกำเนิดลงในรายการที่สองของคุณ

>>> lst2.append(item[0] for item in lst)
>>> lst2
[1, 2, 3, <generator object <genexpr> at 0xb74b3554>]

แต่คุณอาจต้องการให้มันเป็นรายการของรายการแรก

>>> lst2.append([item[0] for item in lst])
>>> lst2
[1, 2, 3, ['a', 1, 'x']]

ตอนนี้เราต่อท้ายรายการของรายการแรกไปยังรายการที่มีอยู่ หากคุณต้องการที่จะเพิ่มชุดรูปแบบรายการไม่ใช่รายการของพวกเขาไปยังรายการที่มีอยู่คุณต้องใช้ list.extend ในกรณีนี้เราไม่ต้องกังวลเกี่ยวกับการเพิ่มตัวสร้างเนื่องจากการขยายจะใช้ตัวสร้างนั้นเพื่อเพิ่มแต่ละรายการที่ได้รับจากที่นั่นเพื่อขยายรายการปัจจุบัน

>>> lst2.extend(item[0] for item in lst)
>>> lst2
[1, 2, 3, 'a', 1, 'x']

หรือ

>>> lst2 + [x[0] for x in lst]
[1, 2, 3, 'a', 1, 'x']
>>> lst2
[1, 2, 3]

https://docs.python.org/3.4/tutorial/datastructures.html#more-on-lists https://docs.python.org/3.4/tutorial/datastructures.html#list-comprehensions


1
คำตอบของคุณดีและสมบูรณ์แบบสำหรับสิ่งที่ดูเหมือนว่า OP ต้องการ แต่ฉันคิดว่าคำappendในคำถามทำให้เกิดความสับสน ดูเหมือนว่าเขา / เธอต้องการเพียงแค่ส่วนความเข้าใจในรายการของโซลูชันของคุณ
beroe
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.