วิธีรับองค์ประกอบที่ n ของรายการไพ ธ อนหรือค่าดีฟอลต์หากไม่มี


144

ฉันกำลังมองหารายการเทียบเท่าใน python ของdictionary.get(key, default)สำหรับรายการ มีสำนวนหนึ่งซับในการรับองค์ประกอบที่ n ของรายการหรือค่าเริ่มต้นหากไม่สามารถใช้ได้?

ตัวอย่างเช่นรับรายการ myList ฉันต้องการได้รับmyList[0]หรือ 5 ถ้าmyListเป็นรายการว่างเปล่า

ขอบคุณ

คำตอบ:


124
l[index] if index < len(l) else default

เพื่อสนับสนุนดัชนีลบเราสามารถใช้:

l[index] if -len(l) <= index < len(l) else default

3
ใช้งานไม่ได้หากรายการของคุณไม่มีชื่อเช่นในรายการเข้าใจ
Xiong Chiamiov

9
คุณดูเหมือนจะลืมกรณีของดัชนีลบ เช่น. ควรกลับindex == -1000000 default
nodakai

3
@ โนะดะไกจุดดี บางครั้งฉันถูกกัดโดยสิ่งนี้ x[index] if 0 <= index < len(x) else defaultจะดีกว่านี้หากindexเคยเป็นลบ
เบ็นฮอยต์

3
@ nodakai ว้าว - เป็นตัวอย่างที่ดีว่าทำไมมันถึงดีกว่าถ้าใช้ลอง / ยกเว้น, แทนที่จะลองใช้รหัสทดสอบอย่างถูกต้องจึงไม่ล้มเหลว ฉันยังคงไม่ชอบลอง / ยกเว้นสำหรับกรณีที่ฉันรู้ว่าจะเกิดขึ้น แต่นี่เป็นการเพิ่มความตั้งใจของฉันในการพิจารณา
ToolmakerSteve

6
@ToolmakerSteve: สูตรของคุณvalid_index()ไม่ถูกต้อง ดัชนีเชิงลบเป็นกฎหมายในหลาม - -len(l) <= index < len(l)มันควรจะเป็น
ทิม Pietzcker

57
try:
   a = b[n]
except IndexError:
   a = default

แก้ไข: ฉันลบเช็คสำหรับ TypeError - น่าจะดีกว่าเพื่อให้ผู้เรียกจัดการสิ่งนี้


3
ฉันชอบสิ่งนี้. เพียงแค่ล้อมรอบฟังก์ชั่นเพื่อที่คุณจะสามารถเรียกมันด้วยการวนซ้ำในฐานะอาร์กิวเมนต์ อ่านง่ายกว่า
Noufal Ibrahim

35
(a[n:]+[default])[0]

นี่อาจจะดีกว่าเมื่อโตaขึ้น

(a[n:n+1]+[default])[0]

งานนี้เพราะถ้าa[n:]เป็นรายการที่ว่างเปล่าถ้าn => len(a)

นี่คือตัวอย่างของการทำงานกับ range(5)

>>> range(5)[3:4]
[3]
>>> range(5)[4:5]
[4]
>>> range(5)[5:6]
[]
>>> range(5)[6:7]
[]

และแสดงออกอย่างเต็มที่

>>> (range(5)[3:4]+[999])[0]
3
>>> (range(5)[4:5]+[999])[0]
4
>>> (range(5)[5:6]+[999])[0]
999
>>> (range(5)[6:7]+[999])[0]
999

5
คุณจะเขียนมันเป็นรหัสจริงโดยไม่มีความคิดเห็นอธิบายไหม?
ปีเตอร์แฮนเซน

1
@ Peter Hansen เท่านั้นถ้าฉันเล่นกอล์ฟ;) อย่างไรก็ตามมันใช้ได้กับPython ทุกรุ่น คำตอบที่ได้รับการยอมรับจะใช้ได้เฉพาะวันที่ 2.5+
John La Rooy

3
มันใช้การสร้างรายการชั่วคราว 3 รายการและเข้าถึงดัชนี 2 รายการเพื่อเลือกรายการ
Joachim Jablon

ในขณะที่ฉันไม่เคยทำสิ่งนี้ในรหัส "ของจริง" มันเป็นหนึ่งในสายการบินที่กระชับที่ฉันสามารถใช้ในงูหลาม REPL ได้อย่างง่ายดายดังนั้นคุณจะได้รับการโหวตของฉัน
Cookyt

next(iter(lst[i:i+1]), default)- เป็นอีกหนึ่งรายการในการแข่งขันแบบ liners one-liners ที่น่าเกลียด
jfs

28

เพิ่งค้นพบว่า:

next(iter(myList), 5)

iter(l)ส่งกลับ iterator บนmyList, next()กินองค์ประกอบแรกของ iterator และยกStopIterationข้อผิดพลาด แต่ถ้าเรียกว่ามีค่าเริ่มต้นซึ่งเป็นกรณีที่นี่อาร์กิวเมนต์ที่สอง5

ใช้งานได้เฉพาะเมื่อคุณต้องการองค์ประกอบที่ 1 ซึ่งเป็นกรณีในตัวอย่างของคุณ แต่ไม่ใช่ในคำถามที่คุณถามดังนั้น ...

นอกจากนี้มันไม่จำเป็นต้องสร้างรายการชั่วคราวในหน่วยความจำและทำงานได้ทุกประเภท iterable แม้ว่าจะไม่มีชื่อ (ดูความเห็นของ Xiong Chiamiov ในคำตอบของ gruszczy)


3
รวมกับคำตอบอื่น ๆ : next(iter(myList[n:n+1]), 5) ตอนนี้มันทำงานได้สำหรับnองค์ประกอบที่
Alfe

ที่จะไม่ทำงานกับรายการที่ไม่ใช่ เมื่อถึงจุดนี้ให้ลอง: ยกเว้นการใช้ IndexError อ่านเหมือนไอเดียที่ดีกว่า นอกจากนี้ยังสร้างรายการในหน่วยความจำ
Joachim Jablon

tryแตกต่างไม่ได้เป็นหนึ่งซับ (ขอถามโดย OP) ใช้งานได้กับรายการเพราะmyListเป็นรายการตามที่ระบุโดย OP (เพื่อความแม่นยำเป็นสิ่งที่สามารถจัดทำดัชนีได้) การสร้างสำเนาในหน่วยความจำไม่ใช่ค่าใช้จ่ายที่นี่เพราะฉันสร้างรายการองค์ประกอบเดียว (หรือไม่มี) ที่นี่ แน่นอนว่าค่าใช้จ่ายเล็กน้อย แต่ไม่คุ้มค่าที่จะกล่าวถึงเว้นแต่คุณจะทำอย่างนั้นเป็นล้านครั้ง แต่ฉันคิดว่าการสร้างและจับIndexErrorข้อยกเว้นอาจมีค่าใช้จ่ายสูงกว่า
Alfe

ความสามารถในการอ่านมีค่า :) ถ้าคุณอยู่ในจุดที่การสร้าง IndexError มีค่าใช้จ่ายสูงคุณอาจต้องทำทุกอย่างใน Python
Joachim Jablon

20
(L[n:n+1] or [somedefault])[0]

1
+1 เพราะนี่ทำให้ฉันเรียนรู้ว่า[] or ...ทำอะไร อย่างไรก็ตามโดยส่วนตัวแล้วฉันจะใช้โซลูชันที่ได้รับการยอมรับเท่านั้นเพราะอ่านได้ง่าย (สำหรับผู้เริ่มใช้) จริงอยู่ที่มีการห่อไว้ใน 'def' พร้อมความคิดเห็นจะทำให้ส่วนใหญ่ไม่ใช่ประเด็น
ToolmakerSteve

เกิดอะไรขึ้นถ้าL[n] == FalseหรือL[n] == NoneหรือL[n] == []หรือมากกว่าทั่วโลกอะไรที่ประเมินเท็จ?
Joachim Jablon

@JoachimJablon: ยังใช้งานได้ ชิ้นส่งคืนรายการและ[False]เป็นจริง
Ignacio Vazquez-Abrams

โอ้ไม่ได้ตระหนักถึงรายการที่ถูกตรวจสอบและไม่คุ้มค่าแน่นอน
Joachim Jablon

ทำไมคุณห่อสิ่งนี้ด้วยสิ่งอันดับ? ฉันคิดว่าmyval = l[n:n+1] or [somedefault]จะทำงานได้ดี
Rotareti

8

... กำลังมองหารายการเทียบเท่าใน python ของdict.get(key, default)สำหรับรายการ

มีสูตร itertoolsที่ทำเพื่อ iterables ทั่วไป เพื่อความสะดวกคุณสามารถ> pip install more_itertoolsและนำเข้าห้องสมุดบุคคลที่สามซึ่งใช้สูตรดังกล่าวสำหรับคุณ:

รหัส

import more_itertools as mit


mit.nth([1, 2, 3], 0)
# 1    

mit.nth([], 0, 5)
# 5    

รายละเอียด

นี่คือการดำเนินการตามnthสูตร:

def nth(iterable, n, default=None):
    "Returns the nth item or a default value"
    return next(itertools.islice(iterable, n, None), default)

เช่นเดียวกับdict.get()เครื่องมือนี้จะส่งคืนค่าเริ่มต้นสำหรับดัชนีที่หายไป มันใช้กับ iterables ทั่วไป:

mit.nth((0, 1, 2), 1)                                      # tuple
# 1

mit.nth(range(3), 1)                                       # range generator (py3)
# 1

mit.nth(iter([0, 1, 2]), 1)                                # list iterator 
# 1  

2

วิธีแก้ปัญหาราคาถูกคือการทำ dict ด้วยการแจกแจงและใช้.get()ตามปกติเช่น

 dict(enumerate(l)).get(7, my_default)

1

เมื่อรวม @ Joachim's เข้ากับด้านบนคุณสามารถใช้

next(iter(my_list[index:]), default)

ตัวอย่าง:

next(iter(range(10)[8:]), 11)
8
>>> next(iter(range(10)[12:]), 11)
11

หรืออาจชัดเจนมากขึ้น แต่ไม่มี len

my_list[index] if my_list[index:] else default

1

ใช้ Python 3.4 ของcontextlib.suppress(exceptions)การสร้างวิธีการที่คล้ายกันgetitem()getattr()

import contextlib

def getitem(iterable, index, default=None):
    """Return iterable[index] or default if IndexError is raised."""
    with contextlib.suppress(IndexError):
        return iterable[index]
    return default
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.