วิธีรับตำแหน่งรายการในรายการ


169

ฉันกำลังวนซ้ำรายการและฉันต้องการพิมพ์ดัชนีของรายการหากตรงตามเงื่อนไข ฉันจะทำสิ่งนี้ได้อย่างไร

ตัวอย่าง:

testlist = [1,2,3,5,3,1,2,1,6]
for item in testlist:
    if item == 1:
        print position

คำตอบ:


280

อืมม มีคำตอบที่มีรายการความเข้าใจที่นี่ แต่มันหายไป

ที่นี่:

 [i for i,x in enumerate(testlist) if x == 1]

ตัวอย่าง:

>>> testlist
[1, 2, 3, 5, 3, 1, 2, 1, 6]
>>> [i for i,x in enumerate(testlist) if x == 1]
[0, 5, 7]

ปรับปรุง:

ตกลงคุณต้องการนิพจน์ตัวสร้างเราจะมีตัวสร้างนิพจน์ นี่คือรายการความเข้าใจอีกครั้งใน for for loop:

>>> for i in [i for i,x in enumerate(testlist) if x == 1]:
...     print i
... 
0
5
7

ตอนนี้เราจะสร้างเครื่องกำเนิด ...

>>> (i for i,x in enumerate(testlist) if x == 1)
<generator object at 0x6b508>
>>> for i in (i for i,x in enumerate(testlist) if x == 1):
...     print i
... 
0
5
7

และเพียงพอเราสามารถกำหนดให้ตัวแปรและใช้จากที่นั่น ...

>>> gen = (i for i,x in enumerate(testlist) if x == 1)
>>> for i in gen: print i
... 
0
5
7

และคิดว่าฉันเคยเขียน FORTRAN


6
หลังจาก 25 ปีของการตั้งคำถามเกี่ยวกับการเขียนโปรแกรมที่ใช้งานได้ฉันคิดว่าในที่สุดฉันก็ได้รับเบาะแส รายการความเข้าใจคือดาระเบิด
Charlie Martin

15
ฉันคิดว่าคุณหมายถึง "ตัวอักษรเดียว" และตรงไปตรงมาชื่ออีกต่อไปในตัวอย่างนี้จะไม่มีเนื้อหาข้อมูลเพิ่มเติม
Charlie Martin

2
ขอบคุณสำหรับคำตอบที่ดี ฉันคิดว่าความคิดเห็นของ @ nailer อาจเกี่ยวข้องกับความจริงที่ว่าคุณใช้ 'i' ในสองบริบทที่แตกต่างกันในบรรทัดเดียวในตัวอย่างของตัวสร้าง; หนึ่งในความเข้าใจและอื่น ๆ เพื่อย้ำผ่านมัน ฉันรู้ว่ามันโยนฉันออกไปหนึ่งวินาที
สีน้ำตาล

1
@CharlieMartin คุณใช้ 'i' สำหรับดัชนีแทนที่จะเป็นรายการต่อหนึ่งหลักการทั่วไปสำหรับตัวแปรอักขระเดี่ยว การตั้งชื่อดัชนี 'ดัชนี' และรายการ 'รายการ' จะเป็นการลบความคลุมเครือ นอกจากนี้คุณกำลังตอบกลับผู้ปกครองที่ใช้ 'รายการ' และ 'ตำแหน่ง' และเป็นมารยาทที่ดีที่จะไม่เปลี่ยนชื่อบางส่วนของรหัสต้นฉบับในคำตอบของคุณ
mikemaccana

1
ไวยากรณ์สุด: o) คุณสามารถรับพารามิเตอร์บรรทัดคำสั่งได้อย่างง่ายดาย ปล่อยให้มีข้อโต้แย้งargs = ['x', '-p1', 'v1', '-p2', 'v2']มากมาย: . จากนั้นคำสั่งargs[[i for i, x in enumerate(args) if x == '-p1'][0] + 1]จะกลับมา'v1'
Theodor Keinstein

170

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

print testlist.index(element)

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

if element in testlist:
    print testlist.index(element)

หรือ

print(testlist.index(element) if element in testlist else None)

หรือ "วิธี pythonic" ซึ่งฉันไม่ชอบมากเพราะรหัสไม่ชัดเจน แต่บางครั้งก็มีประสิทธิภาพมากกว่า

try:
    print testlist.index(element)
except ValueError:
    pass

5
แทนที่จะทดสอบก่อนเข้าใช้คุณสามารถลองและตรวจสอบได้ValueError
kratenko

ฉันคิดว่าเขาต้องการค้นหาเหตุการณ์ที่เกิดขึ้นทั้งหมดคุณดูเหมือนจะให้สิ่งแรกเท่านั้น
tfv

@tfv ฉันไม่เห็นว่าคุณจะได้ข้อสรุปอย่างไรตั้งแต่คำถามระบุว่า "รายการ" และไม่ใช่ "รายการ"
mmj

40

ใช้การแจกแจง:

testlist = [1,2,3,5,3,1,2,1,6]
for position, item in enumerate(testlist):
    if item == 1:
        print position

10
for i in xrange(len(testlist)):
  if testlist[i] == 1:
    print i

xrange แทนช่วงตามที่ร้องขอ (ดูความคิดเห็น)


แทนที่ range () ด้วย xrange () - range () สร้างรายการ xrange () สร้าง iterator xrange () ใช้หน่วยความจำน้อยกว่า waaaay และการโทรแบบ inital นั้นเร็วกว่า
gnud

2
ฉันเห็นด้วยกับรายการใหญ่ในโปรแกรมหลาม 2 โปรดทราบว่า 'ช่วง' จะยังคงทำงานได้ใน python 3 (และทำงานเหมือน xrange IIRC) 'xrange' กำลังไปตามทางของไดโนเสาร์
jakber

2
อัปเดต: xrangeมีการลดขนาดใน Python 3.x เนื่องจากใหม่rangeคือรุ่นเก่าxrange
tim-oh

5

นี่เป็นอีกวิธีในการทำสิ่งนี้:

try:
   id = testlist.index('1')
   print testlist[id]
except ValueError:
   print "Not Found"



1

หากรายการของคุณมีขนาดใหญ่พอและคุณคาดหวังว่าจะพบมูลค่าในดัชนีเพียงเล็กน้อยให้พิจารณาว่ารหัสนี้สามารถทำงานได้เร็วขึ้นมากเพราะคุณไม่ต้องวนซ้ำทุกค่าในรายการ

lookingFor = 1
i = 0
index = 0
try:
  while i < len(testlist):
    index = testlist.index(lookingFor,i)
    i = index + 1
    print index
except ValueError: #testlist.index() cannot find lookingFor
  pass

หากคุณคาดหวังว่าจะพบมูลค่ามากคุณก็ควรผนวก "ดัชนี" ไว้ในรายการแล้วพิมพ์รายการท้ายเพื่อประหยัดเวลาต่อการทำซ้ำ


ฉันทำการทดสอบเวลา เทคนิคความเข้าใจในรายการจะทำงานเร็วกว่าโค้ดนี้ 38% (ฉันแทนที่คำสั่งการพิมพ์ของคุณด้วย outputlist.append call)
Deestan

ฉันยังทำการทดสอบกับขนาดรายการของค่าสุ่ม 100,000 ระหว่าง 1 ถึง 100 รหัสที่ฉันเขียนนั้นในบางกรณีเร็วเป็นสองเท่า ไม่มีการทดสอบเวลาเทียบได้กับการสมัครของผู้โพสต์ (พวกเขาต้องทดสอบตัวเองเพื่อให้แน่ใจว่าแน่นอน) ฉันขอโทษถ้าความคิดเห็นของฉันเป็นอันตรายต่อโพสต์นี้

0

ฉันคิดว่าอาจเป็นประโยชน์ในการใช้ curselection () วิธีการจากห้องสมุด thte Tkinter:

from Tkinter import * 
listbox.curselection()

วิธีนี้ใช้ได้กับวิดเจ็ตกล่องรายการ Tkinter ดังนั้นคุณจะต้องสร้างหนึ่งในนั้นแทนรายการ

นี่จะส่งคืนตำแหน่งดังนี้:

('0',) (แม้ว่า Tkinter เวอร์ชั่นที่ใหม่กว่าอาจส่งคืนรายการของ ints แทน)

ซึ่งสำหรับตำแหน่งแรกและหมายเลขจะเปลี่ยนตามตำแหน่งรายการ

สำหรับข้อมูลเพิ่มเติมดูที่หน้านี้: http://effbot.org/tkinterbook/listbox.htm

ทักทาย.


1
ความคิดที่น่าสนใจ เนื่องจากสิ่งนี้ต้องการการนำเข้าทั้งไลบรารี Tkinter ทั้งหมดจึงไม่ใช่วิธีที่มีประสิทธิภาพที่สุดในการแก้ปัญหา
seaotternerd

3
นี่เป็นเส้นทางที่ไม่มีประสิทธิภาพและคดเคี้ยวซึ่งฉันบอกว่ามันเป็นคำตอบที่ผิดแม้ว่ามันจะตอบคำถาม

คำตอบนี้ไม่เกี่ยวข้องกับคำถาม
Cody Piersall

0

ทำไมสิ่งที่ซับซ้อน?

testlist = [1,2,3,5,3,1,2,1,6]
for position, item in enumerate(testlist):
    if item == 1:
        print position

0

เพียงเพื่อแสดงตัวอย่างที่สมบูรณ์พร้อมกับสิ่งinput_listที่มีsearies1(ตัวอย่าง: input_list [0]) ที่คุณต้องการค้นหาseries2 (เช่น: input_list [1]) และรับดัชนีชุดที่ 2 หากมีอยู่ในซีรีส์ 1

หมายเหตุ: คุณcertain conditionจะแสดงออกด้วยแลมบ์ดาหากเงื่อนไขง่าย

input_list = [[1,2,3,4,5,6,7],[1,3,7]]
series1 = input_list[0]
series2 = input_list[1]
idx_list = list(map(lambda item: series1.index(item) if item in series1 else None, series2))
print(idx_list)

เอาท์พุท:

[0, 2, 6]

-2
testlist = [1,2,3,5,3,1,2,1,6]
for id, value in enumerate(testlist):
    if id == 1:
        print testlist[id]

ฉันเดาว่ามัน exacly สิ่งที่คุณต้องการ ;-) 'id' จะเป็นดัชนีของค่าในรายการเสมอ

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