วิธีรับองค์ประกอบแรกในรายการสิ่งอันดับ?


178

ฉันมีรายการเช่นด้านล่างที่องค์ประกอบแรกคือ ID และอื่น ๆ ที่เป็นสตริง:

[(1, u'abc'), (2, u'def')]

ฉันต้องการสร้างรายการของรหัสจากรายการของ tuples เท่านั้นด้านล่าง:

[1,2]

ฉันจะใช้รายการนี้__inดังนั้นจึงจำเป็นต้องเป็นรายการค่าจำนวนเต็ม

คำตอบ:



68

ใช้ฟังก์ชั่นซิปเพื่อแยกองค์ประกอบ:

>>> inpt = [(1, u'abc'), (2, u'def')]
>>> unzipped = zip(*inpt)
>>> print unzipped
[(1, 2), (u'abc', u'def')]
>>> print list(unzipped[0])
[1, 2]

แก้ไข (@BradSolomon): การทำงานด้านบนสำหรับ Python 2.x โดยที่zipส่งคืนรายการ

ใน Python 3.x ให้zipผลตอบแทนเป็นตัววนซ้ำและสิ่งต่อไปนี้จะเทียบเท่ากับด้านบน:

>>> print(list(list(zip(*inpt))[0]))
[1, 2]

ต้องนำเข้าแยกจากกันหรือไม่
JuliandotNut

2
@JuliandotNut ไม่มันเป็นฟังก์ชันในตัว (ใน Python 2.x)
WayneSan

22

คุณหมายถึงอะไรเช่นนี้

new_list = [ seq[0] for seq in yourlist ]

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

ที่นี่ฉันได้สร้างรายการแบนเพราะโดยทั่วไปดูเหมือนว่ามีประโยชน์มากกว่าการสร้างรายการ 1 องค์ประกอบ tuples แต่คุณสามารถสร้างรายชื่อของ 1 tuples องค์ประกอบโดยเพียงแค่การแทนที่ด้วยseq[0](seq[0],)


ฉันลองแล้ว มันให้ข้อผิดพลาดนี้:int() argument must be a string or a number, not 'QuerySet'
wasimbhalli

4
@wasimbhalli - int()ไม่มีวิธีแก้ไขปัญหาของฉันดังนั้นข้อยกเว้นที่คุณเห็นจะต้องปรากฏในภายหลังในรหัส
mgilson

ฉันได้อัปเดตคำถามแล้วฉันต้องใช้รายการนี้ในภายหลัง__inเพื่อกรองข้อมูล
wasimbhalli

คือ__inอะไร - จากตัวอย่างอินพุตที่คุณให้มาสิ่งนี้จะสร้างรายการจำนวนเต็ม อย่างไรก็ตามหากรายการสิ่งอันดับของคุณไม่ได้เริ่มต้นด้วยจำนวนเต็มคุณจะไม่ได้รับจำนวนเต็มและคุณจะต้องทำให้เป็นจำนวนเต็มผ่านintหรือพยายามหาสาเหตุที่องค์ประกอบแรกของคุณไม่สามารถแปลงเป็นจำนวนเต็มได้
mgilson

ไม่new_list = [ seq[0] for seq in yourlist if type(seq[0]) == int]ทำงานหรือไม่
pR0Ps

11

คุณสามารถใช้ "tuple unpacking":

>>> my_list = [(1, u'abc'), (2, u'def')]
>>> my_ids = [idx for idx, val in my_list]
>>> my_ids
[1, 2]

ที่ย้ำเวลาในแต่ละ tuple เป็นจำนวนมาก ๆ และค่านิยมที่ได้รับการตั้งค่าให้ตัวแปรและidxval

>>> x = (1, u'abc')
>>> idx, val = x
>>> idx
1
>>> val
u'abc'

8

นี่คือสิ่งที่operator.itemgetterมีไว้เพื่อ

>>> a = [(1, u'abc'), (2, u'def')]
>>> import operator
>>> b = map(operator.itemgetter(0), a)
>>> b
[1, 2]

itemgetterคำสั่งส่งกลับฟังก์ชั่นที่ส่งกลับดัชนีขององค์ประกอบที่คุณระบุ มันเหมือนกับการเขียน

>>> b = map(lambda x: x[0], a)

แต่ผมพบว่าitemgetterเป็นที่ชัดเจนและที่ชัดเจนมากขึ้น

สิ่งนี้มีประโยชน์สำหรับการสร้างข้อความค้นหาแบบย่อ ตัวอย่างเช่น,

>>> c = sorted(a, key=operator.itemgetter(0), reverse=True)
>>> c
[(2, u'def'), (1, u'abc')]

7

จากมุมมองประสิทธิภาพใน python3.X

  • [i[0] for i in a]และlist(zip(*a))[0]เทียบเท่า
  • พวกเขาเร็วกว่า list(map(operator.itemgetter(0), a))

รหัส

import timeit


iterations = 100000
init_time = timeit.timeit('''a = [(i, u'abc') for i in range(1000)]''', number=iterations)/iterations
print(timeit.timeit('''a = [(i, u'abc') for i in range(1000)]\nb = [i[0] for i in a]''', number=iterations)/iterations - init_time)
print(timeit.timeit('''a = [(i, u'abc') for i in range(1000)]\nb = list(zip(*a))[0]''', number=iterations)/iterations - init_time)

เอาท์พุต

3.491014136001468e-05

3.422205176000717e-05


6

ถ้าสิ่งอันดับเป็นเอกลักษณ์สิ่งนี้สามารถใช้งานได้

>>> a = [(1, u'abc'), (2, u'def')]
>>> a
[(1, u'abc'), (2, u'def')]
>>> dict(a).keys()
[1, 2]
>>> dict(a).values()
[u'abc', u'def']
>>> 

4
สิ่งนี้จะสูญเสียคำสั่ง มันอาจจะทำงานกับordereddictแม้ว่า
Tim Tisdall

ถ้า 2 หรือมากกว่า tuples มีองค์ประกอบแรกเดียวกันกว่าวิธีการแก้ปัญหาของคุณจะไม่ทำงาน
kederrac

3

เมื่อฉันวิ่ง (ตามที่แนะนำข้างต้น):

>>> a = [(1, u'abc'), (2, u'def')]
>>> import operator
>>> b = map(operator.itemgetter(0), a)
>>> b

แทนที่จะกลับมา:

[1, 2]

ฉันได้รับสิ่งนี้เป็นผลตอบแทน:

<map at 0xb387eb8>

ฉันพบว่าฉันต้องใช้ list ():

>>> b = list(map(operator.itemgetter(0), a))

เพื่อส่งคืนรายการสำเร็จโดยใช้คำแนะนำนี้ ที่กล่าวว่าฉันมีความสุขกับการแก้ปัญหานี้ขอบคุณ (ทดสอบ / รันโดยใช้ Spyder, คอนโซล iPython, Python v3.6)


3

ฉันคิดว่ามันอาจจะมีประโยชน์ในการเปรียบเทียบ runtimes ของวิธีการที่แตกต่างกันดังนั้นฉันทำมาตรฐาน (ใช้ห้องสมุดsimple_benchmark )

I) เกณฑ์มาตรฐานมีสิ่งอันดับ 2 องค์ประกอบ ป้อนคำอธิบายรูปภาพที่นี่

ตามที่คุณคาดหวังว่าจะเลือกองค์ประกอบแรกจากสิ่งอันดับโดยดัชนี0แสดงให้เห็นว่าเป็นทางออกที่เร็วที่สุดใกล้กับวิธีการแก้ปัญหาการบรรจุโดยคาดหวังว่าค่า 2 ค่า

import operator
import random

from simple_benchmark import BenchmarkBuilder

b = BenchmarkBuilder()



@b.add_function()
def rakesh_by_index(l):
    return [i[0] for i in l]


@b.add_function()
def wayneSan_zip(l):
    return list(list(zip(*l))[0])


@b.add_function()
def bcattle_itemgetter(l):
     return list(map(operator.itemgetter(0), l))


@b.add_function()
def ssoler_upacking(l):
    return [idx for idx, val in l]

@b.add_function()
def kederrack_unpacking(l):
    return [f for f, *_ in l]



@b.add_arguments('Number of tuples')
def argument_provider():
    for exp in range(2, 21):
        size = 2**exp
        yield size, [(random.choice(range(100)), random.choice(range(100))) for _ in range(size)]


r = b.run()
r.plot()

II) เกณฑ์มาตรฐานที่มีสิ่งอันดับ 2 หรือมากกว่าองค์ประกอบ ป้อนคำอธิบายรูปภาพที่นี่

import operator
import random

from simple_benchmark import BenchmarkBuilder

b = BenchmarkBuilder()

@b.add_function()
def kederrack_unpacking(l):
    return [f for f, *_ in l]


@b.add_function()
def rakesh_by_index(l):
    return [i[0] for i in l]


@b.add_function()
def wayneSan_zip(l):
    return list(list(zip(*l))[0])


@b.add_function()
def bcattle_itemgetter(l):
     return list(map(operator.itemgetter(0), l))


@b.add_arguments('Number of tuples')
def argument_provider():
    for exp in range(2, 21):
        size = 2**exp
        yield size, [tuple(random.choice(range(100)) for _
                     in range(random.choice(range(2, 100)))) for _ in range(size)]

from pylab import rcParams
rcParams['figure.figsize'] = 12, 7

r = b.run()
r.plot()

0

สิ่งเหล่านั้นเป็นสิ่งอันดับไม่ใช่ชุด คุณสามารถทำได้:

l1 = [(1, u'abc'), (2, u'def')]
l2 = [(tup[0],) for tup in l1]
l2
>>> [(1,), (2,)]

2
ไม่ใช่สิ่งที่ถูกถามจริงๆ
นักฟิสิกส์บ้า

0

คุณสามารถแกะ tuples ของคุณและรับเฉพาะองค์ประกอบแรกโดยใช้ list comprehension:

l = [(1, u'abc'), (2, u'def')]
[f for f, *_ in l]

เอาท์พุท:

[1, 2]

สิ่งนี้จะได้ผลไม่ว่าคุณจะมีองค์ประกอบกี่ตัวในสิ่งอันดับ:

l = [(1, u'abc'), (2, u'def', 2, 4, 5, 6, 7)]
[f for f, *_ in l]

เอาท์พุท:

[1, 2]

0

ฉันสงสัยว่าทำไมไม่มีใครแนะนำให้ใช้ numpy แต่ตอนนี้หลังจากตรวจสอบฉันเข้าใจ มันอาจจะไม่ดีที่สุดสำหรับอาร์เรย์ประเภทผสม

นี่จะเป็นวิธีแก้ปัญหาใน numpy:

>>> import numpy as np

>>> a = np.asarray([(1, u'abc'), (2, u'def')])
>>> a[:, 0].astype(int).tolist()
[1, 2]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.