การค้นหาดัชนีของรายการในรายการ


3179

รับรายการ["foo", "bar", "baz"]และรายการในรายการ"bar"ฉันจะรับดัชนี ( 1) ใน Python ได้อย่างไร


6
คุณจะกลับมา: [1] ดัชนีต่ำที่สุดในกรณีที่มีหลายอินสแตนซ์ของ"bar", [2] ดัชนีทั้งหมดของ"bar"?
Ṃųỻịgǻňạcểơửṩ

4
a) มีการรับประกันว่ารายการนั้นอยู่ในรายการหรือไม่ว่าเราควรจัดการกรณีข้อผิดพลาดหรือไม่? (คืนค่าไม่มี / เพิ่ม ValueError) b) รายการรายการรับประกันว่าไม่ซ้ำกันและเราควรส่งคืนดัชนีแรกของการแข่งขันหรือดัชนีทั้งหมดหรือไม่
smci

ดูคำตอบด้วยการรวม numpy อาร์เรย์ numpy นั้นมีประสิทธิภาพมากกว่ารายการ Python หากรายการนั้นสั้นก็ไม่มีปัญหาในการสร้างสำเนาของมันจากรายการ Python ถ้าไม่ใช่ก็เป็นไปได้ว่าคุณควรพิจารณาจัดเก็บองค์ประกอบไว้ในอาร์เรย์ numpy ในตอนแรก
Athanassios

คำตอบ:


4480
>>> ["foo", "bar", "baz"].index("bar")
1

การอ้างอิง: โครงสร้างข้อมูล> เพิ่มเติมเกี่ยวกับรายการ

Caveats ปฏิบัติตาม

โปรดทราบว่าแม้ว่านี่อาจเป็นวิธีที่ดีที่สุดในการตอบคำถามตามที่ถามแต่indexเป็นองค์ประกอบที่ค่อนข้างอ่อนแอของlistAPI และฉันจำไม่ได้ว่าครั้งสุดท้ายที่ฉันใช้มันด้วยความโกรธ มันชี้ให้เห็นฉันในความคิดเห็นที่เพราะคำตอบนี้มีการอ้างอิงอย่างหนักควรทำให้สมบูรณ์มากขึ้น คำเตือนบางอย่างเกี่ยวกับการlist.indexติดตาม มันอาจจะคุ้มค่าเริ่มแรกลองดูที่เอกสารของมัน

list.index(x[, start[, end]])

ดัชนีย้อนกลับ zero-based ในรายการของรายการแรกที่มีค่าเท่ากับx เพิ่ม a ValueErrorหากไม่มีรายการดังกล่าว

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

ความซับซ้อนของเวลาเชิงเส้นในความยาวของรายการ

การindexโทรจะตรวจสอบทุกองค์ประกอบของรายการตามลำดับจนกว่าจะพบการแข่งขัน หากรายการของคุณมีความยาวและคุณไม่ทราบว่าจะเกิดขึ้นที่ไหนในรายการการค้นหานี้อาจกลายเป็นปัญหาคอขวด ในกรณีนี้คุณควรพิจารณาโครงสร้างข้อมูลที่แตกต่างกัน โปรดทราบว่าถ้าคุณรู้ว่าจะหาคู่ที่ตรงไหนคุณสามารถให้indexคำใบ้ ตัวอย่างเช่นในตัวอย่างนี้l.index(999_999, 999_990, 1_000_000)นี้คำสั่งขนาดประมาณห้าคำสั่งเร็วกว่าทางตรงl.index(999_999)เพราะในอดีตมีเพียงการค้นหา 10 รายการในขณะที่รายการหลังค้นหาหนึ่งล้าน:

>>> import timeit
>>> timeit.timeit('l.index(999_999)', setup='l = list(range(0, 1_000_000))', number=1000)
9.356267921015387
>>> timeit.timeit('l.index(999_999, 999_990, 1_000_000)', setup='l = list(range(0, 1_000_000))', number=1000)
0.0004404920036904514

ส่งคืนดัชนีของ จับคู่แรกไปยังอาร์กิวเมนต์ของมัน

การเรียกร้องให้indexค้นหารายการตามลำดับจนกระทั่งพบการแข่งขันและหยุดอยู่ที่นั่นหากคุณคาดว่าจะต้องการดัชนีการจับคู่เพิ่มเติมคุณควรใช้ list comprehension หรือ expression ของเครื่องกำเนิด

>>> [1, 1].index(1)
0
>>> [i for i, e in enumerate([1, 2, 1]) if e == 1]
[0, 2]
>>> g = (i for i, e in enumerate([1, 2, 1]) if e == 1)
>>> next(g)
0
>>> next(g)
2

สถานที่ส่วนใหญ่ที่ฉันเคยใช้ indexตอนนี้ฉันใช้รายการความเข้าใจหรือนิพจน์ตัวสร้างเนื่องจากพวกมันสามารถหาได้ทั่วไปมากกว่า ดังนั้นหากคุณกำลังพิจารณาที่indexจะลองดูคุณสมบัติของ Python ที่ยอดเยี่ยมเหล่านี้

โยนถ้าองค์ประกอบที่ไม่ได้อยู่ในรายการ

การเรียกเพื่อให้ได้indexผลลัพธ์ValueErrorถ้าหากไม่มีรายการอยู่

>>> [1, 1].index(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: 2 is not in list

หากรายการนั้นอาจไม่มีอยู่ในรายการคุณควรทำอย่างใดอย่างหนึ่ง

  1. ตรวจสอบก่อนด้วยitem in my_list(วิธีที่สะอาดอ่านง่าย) หรือ
  2. ล้อมindexสายไว้ในtry/exceptบล็อกที่จับได้ValueError(อาจเร็วกว่าอย่างน้อยเมื่อรายการที่ต้องการค้นหายาวและมักจะมีรายการอยู่)

20
ดัชนีส่งคืนรายการแรกที่มีค่าเป็น "bar" หากรายการ "bar" มีอยู่สองครั้งคุณจะไม่พบกุญแจสำหรับ "bar" ตัวที่สอง ดูเอกสาร: docs.python.org/3/tutorial/datastructures.html
mpoletto

2
หากคุณเพียงค้นหาองค์ประกอบหนึ่ง (แรก) ฉันพบว่าindex()เร็วกว่า 90% เร็วกว่ารายการความเข้าใจกับรายการของจำนวนเต็ม
slybloty

โครงสร้างข้อมูลใดที่ควรใช้หากรายการมีความยาวมาก?
izhang05

@izhang: ดัชนีแนะแนวบางอย่างเช่น {องค์ประกอบ -> list_index} dict หากองค์ประกอบนั้น hashable และตำแหน่งในรายการนั้นมีความสำคัญ
Alex Coventry

898

สิ่งหนึ่งที่มีประโยชน์มากในการเรียนรู้ Python คือการใช้ฟังก์ชั่นวิธีใช้แบบโต้ตอบ

>>> help(["foo", "bar", "baz"])
Help on list object:

class list(object)
 ...

 |
 |  index(...)
 |      L.index(value, [start, [stop]]) -> integer -- return first index of value
 |

ซึ่งมักจะนำคุณไปสู่วิธีการที่คุณกำลังมองหา


2
bpythonเป็นวิธีที่ใช้งานง่ายในการอ่านเอกสารในรูปแบบอินเทอร์แอคทีฟ
goetzc

@davidavr ใช่ แต่แล้วพวกเราที่เหลือที่อยากจะ google แทนการเลื่อนดูเอกสารช่วยเหลือจะไม่มีตัวเลือกที่ดีเป็นศูนย์กลางและอยู่ในอันดับนี้ :)
honkaboy

555

คำตอบส่วนใหญ่อธิบายวิธีการค้นหาดัชนีเดี่ยวแต่วิธีการของพวกเขาไม่ได้ส่งคืนดัชนีหลายรายการหากรายการนั้นอยู่ในรายการหลายครั้ง ใช้enumerate():

for i, j in enumerate(['foo', 'bar', 'baz']):
    if j == 'bar':
        print(i)

index()ฟังก์ชั่นเพียงผลตอบแทนที่เกิดขึ้นครั้งแรกในขณะที่enumerate()ผลตอบแทนที่เกิดขึ้นทั้งหมด

ในฐานะที่เป็นรายการความเข้าใจ:

[i for i, j in enumerate(['foo', 'bar', 'baz']) if j == 'bar']

นี่เป็นอีกวิธีแก้ปัญหาเล็ก ๆ ด้วยitertools.count()(ซึ่งค่อนข้างคล้ายกับวิธีแจกแจง):

from itertools import izip as zip, count # izip for maximum efficiency
[i for i, j in zip(count(), ['foo', 'bar', 'baz']) if j == 'bar']

สิ่งนี้มีประสิทธิภาพมากขึ้นสำหรับรายการขนาดใหญ่กว่าการใช้enumerate():

$ python -m timeit -s "from itertools import izip as zip, count" "[i for i, j in zip(count(), ['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 loops, best of 3: 174 usec per loop
$ python -m timeit "[i for i, j in enumerate(['foo', 'bar', 'baz']*500) if j == 'bar']"
10000 loops, best of 3: 196 usec per loop

การแจงนับทำได้ดีกว่าวิธีที่อิงกับดัชนีสำหรับฉันเนื่องจากฉันต้องการรวบรวมดัชนีของสตริงโดยใช้ 'startswith "และฉันต้องรวบรวมเหตุการณ์หลายครั้งหรือมีวิธีใช้ดัชนีกับ" startswith "ที่ฉัน ไม่สามารถคิดออกได้
Tupelo Thistlehead

3
ในมือของฉันรุ่นแจกแจงนั้นเร็วขึ้นเล็กน้อยอย่างต่อเนื่อง รายละเอียดการใช้งานบางอย่างอาจเปลี่ยนแปลงไปนับตั้งแต่มีการโพสต์การวัดด้านบน
อเล็กซ์โคเวนทรี

2
สิ่งนี้ได้รับคำตอบแล้วตั้งแต่ '11: stackoverflow.com/questions/6294179/…
Cristik


132

index()ส่งคืนดัชนีค่าแรก !

| ดัชนี (... )
| L.index (ค่า [เริ่ม, [หยุด]]) -> จำนวนเต็ม - ส่งคืนดัชนีค่าแรก

def all_indices(value, qlist):
    indices = []
    idx = -1
    while True:
        try:
            idx = qlist.index(value, idx+1)
            indices.append(idx)
        except ValueError:
            break
    return indices

all_indices("foo", ["foo","bar","baz","foo"])

2
และถ้าไม่มีอยู่ในรายการ?
Peter Mortensen

1
รายการที่ไม่มีอยู่จะเพิ่ม ValueError
Nam G VU

1
คำตอบนี้จะพอดีดีกว่าที่นี่: stackoverflow.com/questions/6294179/…
Cristik

86

ปัญหาจะเกิดขึ้นหากองค์ประกอบไม่ได้อยู่ในรายการ ฟังก์ชั่นนี้จัดการกับปัญหา:

# if element is found it returns index of element else returns None

def find_element_in_list(element, list_element):
    try:
        index_element = list_element.index(element)
        return index_element
    except ValueError:
        return None


58

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

if 'your_element' in mylist:
    print mylist.index('your_element')
else:
    print None

1
สิ่งนี้ช่วยให้เราหลีกเลี่ยงการลองจับ!
devssh

อย่างไรก็ตามมันอาจซับซ้อนเป็นสองเท่า มีใครตรวจสอบหรือไม่
stefanct

@stefanct ความซับซ้อนของเวลายังคงเป็นเชิงเส้น แต่จะวนซ้ำในรายการสองครั้ง
ApproachDarknessFish

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

44

ฟังก์ชั่นที่นำเสนอทั้งหมดที่นี่ทำซ้ำพฤติกรรมภาษาโดยธรรมชาติ แต่ปิดบังสิ่งที่เกิดขึ้น

[i for i in range(len(mylist)) if mylist[i]==myterm]  # get the indices

[each for each in mylist if each==myterm]             # get the items

mylist.index(myterm) if myterm in mylist else None    # get the first index and fail quietly

ทำไมการเขียนฟังก์ชั่นที่มีการจัดการข้อยกเว้นถ้าภาษามีวิธีการทำสิ่งที่คุณต้องการเอง


9
วิธีที่ 3 ทำซ้ำสองครั้งในรายการใช่ไหม
Eric Duminil

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

41

หากคุณต้องการดัชนีทั้งหมดคุณสามารถใช้NumPy :

import numpy as np

array = [1, 2, 1, 3, 4, 5, 1]
item = 1
np_array = np.array(array)
item_index = np.where(np_array==item)
print item_index
# Out: (array([0, 2, 6], dtype=int64),)

เป็นโซลูชั่นที่ชัดเจนอ่านได้


4
สิ่งที่เกี่ยวกับรายการของสตริงรายการของวัตถุที่ไม่ใช่ตัวเลข ฯลฯ ... ?
กล่องเสียง Decidua

1
คำตอบนี้ควรโพสต์ได้ดีกว่าที่นี่: stackoverflow.com/questions/6294179/…
Cristik

1
นี่คือสิ่งที่ดีที่สุดที่ฉันได้อ่าน อาร์เรย์ที่มีจำนวนมากมีประสิทธิภาพมากกว่ารายการ Python หากรายการนั้นสั้นก็ไม่มีปัญหาในการทำสำเนาของมันจากรายการ Python ถ้าไม่ใช่อย่างนั้นบางทีผู้พัฒนาควรจะพิจารณาจัดเก็บองค์ประกอบในอาร์เรย์ numpy ในตอนแรก
Athanassios

35

การค้นหาดัชนีของรายการที่กำหนดให้มีรายการอยู่ใน Python

สำหรับรายการ["foo", "bar", "baz"]และรายการในรายการ"bar"วิธีที่สะอาดที่สุดในการรับดัชนี (1) ใน Python คืออะไร

แน่นอนว่ามีวิธีดัชนีซึ่งส่งกลับดัชนีของการเกิดครั้งแรก:

>>> l = ["foo", "bar", "baz"]
>>> l.index('bar')
1

มีปัญหาสองสามข้อในวิธีนี้:

  • หากค่าไม่อยู่ในรายการคุณจะได้รับ ValueError
  • หากมีมากกว่าหนึ่งค่าในรายการคุณจะได้รับดัชนีสำหรับค่าแรกเท่านั้น

ไม่มีค่า

หากค่าอาจหายไปคุณจะต้องตรวจสอบ ValueErrorสอบ

คุณสามารถทำได้ด้วยคำจำกัดความที่ใช้ซ้ำได้เช่นนี้:

def index(a_list, value):
    try:
        return a_list.index(value)
    except ValueError:
        return None

และใช้มันเช่นนี้

>>> print(index(l, 'quux'))
None
>>> print(index(l, 'bar'))
1

และข้อเสียของสิ่งนี้คือคุณอาจจะต้องตรวจสอบว่าค่าที่ส่งคืนisหรือis notไม่มี:

result = index(a_list, value)
if result is not None:
    do_something(result)

มีมากกว่าหนึ่งค่าในรายการ

หากคุณมีเหตุการณ์เพิ่มเติมคุณจะไม่ได้รับข้อมูลที่ครบถ้วนด้วยlist.index:

>>> l.append('bar')
>>> l
['foo', 'bar', 'baz', 'bar']
>>> l.index('bar')              # nothing at index 3?
1

คุณอาจระบุในรายการความเข้าใจดัชนี:

>>> [index for index, v in enumerate(l) if v == 'bar']
[1, 3]
>>> [index for index, v in enumerate(l) if v == 'boink']
[]

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

indexes = [index for index, v in enumerate(l) if v == 'boink']
for index in indexes:
    do_something(index)

ดาต้าที่ดีขึ้นด้วยแพนด้า

หากคุณมีหมีแพนด้าคุณสามารถรับข้อมูลนี้ได้ด้วยวัตถุอนุกรม:

>>> import pandas as pd
>>> series = pd.Series(l)
>>> series
0    foo
1    bar
2    baz
3    bar
dtype: object

การตรวจสอบการเปรียบเทียบจะส่งคืนชุดบูลีน:

>>> series == 'bar'
0    False
1     True
2    False
3     True
dtype: bool

ส่งผ่านชุดของ booleans ไปยังซีรี่ส์ผ่านเครื่องหมายห้อยและคุณจะได้รับเฉพาะสมาชิกที่ตรงกัน:

>>> series[series == 'bar']
1    bar
3    bar
dtype: object

หากคุณต้องการเพียงดัชนีแอ็ตทริบิวต์ index จะส่งคืนชุดจำนวนเต็ม:

>>> series[series == 'bar'].index
Int64Index([1, 3], dtype='int64')

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

>>> list(series[series == 'bar'].index)
[1, 3]

ใช่คุณสามารถใช้ list comprehension กับ enumerate ได้เช่นกัน แต่นั่นไม่ใช่ความหรูหราในความคิดของฉัน - คุณกำลังทำการทดสอบเพื่อความเท่าเทียมกันใน Python แทนที่จะปล่อยให้โค้ด builtin ที่เขียนด้วย C จัดการมัน:

>>> [i for i, value in enumerate(l) if value == 'bar']
[1, 3]

นี่เป็นปัญหา XYหรือไม่

ปัญหา XY กำลังถามเกี่ยวกับวิธีแก้ปัญหาที่คุณพยายามแทนที่จะเป็นปัญหาจริงของคุณ

ทำไมคุณคิดว่าคุณต้องการให้ดัชนีกำหนดองค์ประกอบในรายการ

ถ้าคุณรู้คุณค่าแล้วทำไมคุณถึงสนใจว่ามันอยู่ในรายการ?

หากค่าไม่ได้อยู่ที่นั่นการจับค่าValueErrorเป็นสิ่งที่ค่อนข้างละเอียด - และฉันชอบที่จะหลีกเลี่ยงสิ่งนั้น

ฉันมักจะวนซ้ำรายการต่อไปดังนั้นฉันมักจะเก็บตัวชี้ไปยังข้อมูลที่น่าสนใจรับดัชนีที่มีการแจกแจง

หากคุณกำลังบันทึกข้อมูลคุณควรใช้หมีแพนด้าซึ่งมีเครื่องมือที่สง่างามกว่าการใช้ Python ในการแก้ไข

ฉันจำไม่ได้ว่าต้องการlist.indexตัวฉัน อย่างไรก็ตามฉันได้ดูไลบรารี่มาตรฐานของ Python แล้วและฉันก็เห็นการใช้งานที่ยอดเยี่ยมสำหรับมัน

มีมากมายหลายอย่างที่ใช้ในidlelibนั้นสำหรับ GUI และการแยกวิเคราะห์ข้อความ

keywordโมดูลใช้มันเพื่อหาคิดเห็นเครื่องหมายในโมดูลโดยอัตโนมัติงอกรายการคำหลักในทาง metaprogramming

ใน Lib / mailbox.py ดูเหมือนว่าจะใช้งานได้เหมือนแผนที่ที่สั่งซื้อ:

key_list[key_list.index(old)] = new

และ

del key_list[key_list.index(key)]

ใน Lib / http / cookiejar.py ดูเหมือนว่าจะใช้ในการรับเดือนถัดไป:

mon = MONTHS_LOWER.index(mon.lower())+1

ใน Lib / tarfile.py คล้ายกับ distutils เพื่อให้ได้ชิ้นสูงสุด:

members = members[:members.index(tarinfo)]

ใน Lib / pickletools.py:

numtopop = before.index(markobject)

สิ่งที่ประเพณีเหล่านี้ดูเหมือนจะมีเหมือนกันคือพวกเขาดูเหมือนจะทำงานในรายการขนาดที่ จำกัด (สำคัญเนื่องจากเวลาค้นหา O (n) สำหรับ list.index ) และส่วนใหญ่จะใช้ในการแยกวิเคราะห์ (และ UI ในกรณีของ Idle)

ในขณะที่มีกรณีการใช้งานสำหรับพวกเขาจะค่อนข้างผิดปกติ หากคุณพบว่าตัวเองกำลังมองหาคำตอบนี้ถามตัวเองว่าสิ่งที่คุณทำคือการใช้เครื่องมือที่ตรงที่สุดโดยภาษาสำหรับกรณีการใช้งานของคุณ



21

รับเหตุการณ์ทั้งหมดและตำแหน่งของรายการ (เหมือนกัน) หนึ่งรายการขึ้นไปในรายการ

ด้วยการแจกแจง (alist) คุณสามารถเก็บองค์ประกอบแรก (n) นั่นคือดัชนีของรายการเมื่อองค์ประกอบ x เท่ากับสิ่งที่คุณมองหา

>>> alist = ['foo', 'spam', 'egg', 'foo']
>>> foo_indexes = [n for n,x in enumerate(alist) if x=='foo']
>>> foo_indexes
[0, 3]
>>>

มาสร้างฟังก์ชั่น findindex กัน

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

def indexlist(item2find, list_or_string):
  "Returns all indexes of an item in a list or a string"
  return [n for n,item in enumerate(list_or_string) if item==item2find]

print(indexlist("1", "010101010"))

เอาท์พุต


[1, 3, 5, 7]

ง่าย

for n, i in enumerate([1, 2, 3, 4, 1]):
    if i == 1:
        print(n)

เอาท์พุท:

0
4

1
คำตอบนี้ควรโพสต์ได้ดีกว่าที่นี่: stackoverflow.com/questions/6294179/…
Cristik

16

เพียงคุณไปกับ

a = [['hand', 'head'], ['phone', 'wallet'], ['lost', 'stock']]
b = ['phone', 'lost']

res = [[x[0] for x in a].index(y) for y in b]


15

และตอนนี้สำหรับบางสิ่งที่แตกต่างอย่างสิ้นเชิง ...

... ชอบยืนยันการมีอยู่ของรายการก่อนรับดัชนี สิ่งที่ดีเกี่ยวกับวิธีนี้คือฟังก์ชั่นจะส่งกลับรายการดัชนีเสมอ - แม้ว่ามันจะเป็นรายการที่ว่างเปล่า มันทำงานได้กับสตริงเช่นกัน

def indices(l, val):
    """Always returns a list containing the indices of val in the_list"""
    retval = []
    last = 0
    while val in l[last:]:
            i = l[last:].index(val)
            retval.append(last + i)
            last += i + 1   
    return retval

l = ['bar','foo','bar','baz','bar','bar']
q = 'bar'
print indices(l,q)
print indices(l,'bat')
print indices('abcdaababb','a')

เมื่อวางลงในหน้าต่างหลามแบบโต้ตอบ:

Python 2.7.6 (v2.7.6:3a1db0d2747e, Nov 10 2013, 00:42:54) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def indices(the_list, val):
...     """Always returns a list containing the indices of val in the_list"""
...     retval = []
...     last = 0
...     while val in the_list[last:]:
...             i = the_list[last:].index(val)
...             retval.append(last + i)
...             last += i + 1   
...     return retval
... 
>>> l = ['bar','foo','bar','baz','bar','bar']
>>> q = 'bar'
>>> print indices(l,q)
[0, 2, 4, 5]
>>> print indices(l,'bat')
[]
>>> print indices('abcdaababb','a')
[0, 4, 5, 7]
>>> 

ปรับปรุง

หลังจากหนึ่งปีของการพัฒนาหลามแบบหล่นลงผมก็อายด้วยคำตอบดั้งเดิมของฉันดังนั้นการตั้งค่าการบันทึกโดยตรงหนึ่งสามารถใช้รหัสข้างต้นได้อย่างแน่นอน แต่มากวิธีสำนวนมากขึ้นที่จะได้รับพฤติกรรมเดียวกันจะใช้ความเข้าใจรายการพร้อมกับแจกแจง () ฟังก์ชัน

บางสิ่งเช่นนี้

def indices(l, val):
    """Always returns a list containing the indices of val in the_list"""
    return [index for index, value in enumerate(l) if value == val]

l = ['bar','foo','bar','baz','bar','bar']
q = 'bar'
print indices(l,q)
print indices(l,'bat')
print indices('abcdaababb','a')

ซึ่งเมื่อวางลงในหน้าต่างหลามแบบโต้ตอบผลผลิต:

Python 2.7.14 |Anaconda, Inc.| (default, Dec  7 2017, 11:07:58) 
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> def indices(l, val):
...     """Always returns a list containing the indices of val in the_list"""
...     return [index for index, value in enumerate(l) if value == val]
... 
>>> l = ['bar','foo','bar','baz','bar','bar']
>>> q = 'bar'
>>> print indices(l,q)
[0, 2, 4, 5]
>>> print indices(l,'bat')
[]
>>> print indices('abcdaababb','a')
[0, 4, 5, 7]
>>> 

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

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


12

ตัวแปรในคำตอบจาก FMc และ user7177 จะให้ค่าตามคำบอกที่สามารถส่งคืนดัชนีทั้งหมดสำหรับรายการใด ๆ

>>> a = ['foo','bar','baz','bar','any', 'foo', 'much']
>>> l = dict(zip(set(a), map(lambda y: [i for i,z in enumerate(a) if z is y ], set(a))))
>>> l['foo']
[0, 5]
>>> l ['much']
[6]
>>> l
{'baz': [2], 'foo': [0, 5], 'bar': [1, 3], 'any': [4], 'much': [6]}
>>> 

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


1
คำตอบนี้ควรโพสต์ได้ดีกว่าที่นี่: stackoverflow.com/questions/6294179/…
Cristik

10

โซลูชันนี้ไม่ได้มีประสิทธิภาพเทียบเท่ากับผู้อื่น แต่ถ้าคุณเป็นผู้เริ่มต้นและมีความรู้เกี่ยวกับforลูปก็ยังคงเป็นไปได้ที่จะหาดัชนีแรกของรายการขณะที่หลีกเลี่ยง ValueError:

def find_element(p,t):
    i = 0
    for e in p:
        if e == t:
            return i
        else:
            i +=1
    return -1

9

การค้นหาดัชนีของรายการ x ในรายการ L:

idx = L.index(x) if (x in L) else -1

4
ซึ่งจะทำซ้ำอาร์เรย์สองครั้งจึงอาจส่งผลให้เกิดปัญหาประสิทธิภาพการทำงานสำหรับอาร์เรย์ขนาดใหญ่
Cristik

ตกลง. หากรายการมีความยาวมากฉันจะไปหาอย่างอื่น ไม่ควรเป็นเรื่องใหญ่สำหรับรายการขนาดเล็กถึงขนาดกลาง
Ketan

5

เนื่องจากรายการ Python เป็นแบบ zero-based เราจึงสามารถใช้ฟังก์ชัน built-in zip ได้ดังต่อไปนี้:

>>> [i for i,j in zip(range(len(haystack)), haystack) if j == 'needle' ]

โดยที่ "Haystack" เป็นรายการที่มีปัญหาและ "เข็ม" เป็นรายการที่จะมองหา

(หมายเหตุ: ที่นี่เรากำลังทำซ้ำโดยใช้ i เพื่อรับดัชนี แต่ถ้าเราต้องการค่อนข้างที่จะมุ่งเน้นไปที่รายการที่เราสามารถเปลี่ยนเป็น j.)


3
[i สำหรับ i, j ในการแจกแจง (เฮย์สแต็ค) ถ้า j == 'เข็ม'] มีขนาดกะทัดรัดและอ่านง่ายขึ้นฉันคิดว่า
Giovanni G. PY

5
name ="bar"
list = [["foo", 1], ["bar", 2], ["baz", 3]]
new_list=[]
for item in list:
    new_list.append(item[0])
print(new_list)
try:
    location= new_list.index(name)
except:
    location=-1
print (location)

บัญชีนี้ใช้เพื่อดูว่าสตริงไม่ได้อยู่ในรายการด้วยหรือไม่หากไม่มีอยู่ในรายการ location = -1


4

index()วิธีการหลามโยนข้อผิดพลาดหากไม่พบรายการ ดังนั้นคุณสามารถทำให้มันคล้ายกับindexOf()ฟังก์ชันของ JavaScript ซึ่งจะส่งคืน-1หากไม่พบรายการ:

try:
    index = array.index('search_keyword')
except ValueError:
    index = -1

5
อย่างไรก็ตามJavaScriptมีปรัชญาที่ผลลัพธ์แปลก ๆ ดีกว่าข้อผิดพลาดดังนั้นจึงเหมาะสมที่จะส่งคืน -1 แต่ใน Python มันสามารถติดตามบั๊กได้ยากเนื่องจาก -1 ส่งคืนไอเท็มจากส่วนท้ายของรายการ
Sapphire_Brick

3

มีคำตอบที่ใช้งานได้ดีกว่าสำหรับสิ่งนี้

list(filter(lambda x: x[1]=="bar",enumerate(["foo", "bar", "baz", "bar", "baz", "bar", "a", "b", "c"])))

รูปแบบทั่วไปเพิ่มเติม:

def get_index_of(lst, element):
    return list(map(lambda x: x[0],\
       (list(filter(lambda x: x[1]==element, enumerate(lst))))))

1
คำตอบนี้รู้สึกเหมือนอยู่บ้านสำหรับผู้ที่ชื่นชอบการเขียนโปรแกรมScala / การทำงาน
y2k-shubham

3

ลองตั้งชื่อlstให้กับรายการที่คุณมี หนึ่งสามารถแปลงรายการไปlst numpy arrayและจากนั้นใช้numpy.whereเพื่อรับดัชนีของรายการที่เลือกในรายการ ต่อไปนี้เป็นวิธีที่คุณจะใช้งาน

import numpy as np

lst = ["foo", "bar", "baz"]  #lst: : 'list' data type
print np.where( np.array(lst) == 'bar')[0][0]

>>> 1

2

สำหรับผู้ที่มาจากภาษาอื่นเช่นฉันอาจจะมีวงที่เรียบง่ายเข้าใจและใช้งานได้ง่ายขึ้น:

mylist = ["foo", "bar", "baz", "bar"]
newlist = enumerate(mylist)
for index, item in newlist:
  if item == "bar":
    print(index, item)

ฉันขอบคุณสำหรับสิ่งที่แจงนับทำอะไร? . นั่นช่วยให้ฉันเข้าใจ


2

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

นี่คือตัวอย่างของรหัสโดยใช้ Python 3.8 และสูงกว่าไวยากรณ์:

import bisect
from timeit import timeit

def bisect_search(container, value):
    return (
      index 
      if (index := bisect.bisect_left(container, value)) < len(container) 
      and container[index] == value else -1
    )

data = list(range(1000))
# value to search
value = 666

# times to test
ttt = 1000

t1 = timeit(lambda: data.index(value), number=ttt)
t2 = timeit(lambda: bisect_search(data, value), number=ttt)

print(f"{t1=:.4f}, {t2=:.4f}, diffs {t1/t2=:.2f}")

เอาท์พุท:

t1=0.0400, t2=0.0020, diffs t1/t2=19.60

1

หากประสิทธิภาพมีความกังวล:

มันถูกกล่าวถึงในคำตอบมากมายว่าวิธีการของlist.index(item)วิธีการในตัวเป็นอัลกอริทึม O (n) ไม่เป็นไรถ้าคุณต้องทำสิ่งนี้ครั้งเดียว แต่ถ้าคุณต้องการเข้าถึงดัชนีองค์ประกอบหลาย ๆ ครั้งคุณควรสร้างพจนานุกรม (O (n)) ของคู่รายการดัชนีก่อนแล้วจึงเข้าถึงดัชนีที่ O (1) ทุกครั้งที่คุณต้องการ มัน.

หากคุณแน่ใจว่ารายการในรายการของคุณไม่เคยซ้ำคุณสามารถ:

myList = ["foo", "bar", "baz"]

# Create the dictionary
myDict = dict((e,i) for i,e in enumerate(myList))

# Lookup
myDict["bar"] # Returns 1
# myDict.get("blah") if you don't want an error to be raised if element not found.

หากคุณอาจมีองค์ประกอบที่ซ้ำกันและจำเป็นต้องกลับดัชนีทั้งหมดของพวกเขา:

from collections import defaultdict as dd
myList = ["foo", "bar", "bar", "baz", "foo"]

# Create the dictionary
myDict = dd(list)
for i,e in enumerate(myList):
    myDict[e].append(i)

# Lookup
myDict["foo"] # Returns [0, 4]

1

ตามที่ระบุโดย @TerryA คำตอบมากมายจะพูดถึงวิธีค้นหาดัชนีหนึ่งรายการ

more_itertoolsเป็นห้องสมุดบุคคลที่สามที่มีเครื่องมือในการค้นหาดัชนีหลายรายการภายใน iterable

ป.ร. ให้ไว้

import more_itertools as mit


iterable = ["foo", "bar", "baz", "ham", "foo", "bar", "baz"]

รหัส

ค้นหาดัชนีการสังเกตหลายรายการ:

list(mit.locate(iterable, lambda x: x == "bar"))
# [1, 5]

ทดสอบหลายรายการ:

list(mit.locate(iterable, lambda x: x in {"bar", "ham"}))
# [1, 3, 5]

more_itertools.locateดูตัวเลือกมากขึ้นด้วยนอกจากนี้ยังมี > pip install more_itertoolsติดตั้งผ่านทาง


0

ใช้พจนานุกรมโดยประมวลผลรายการก่อนแล้วจึงเพิ่มดัชนีเข้าไป

from collections import defaultdict

index_dict = defaultdict(list)    
word_list =  ['foo','bar','baz','bar','any', 'foo', 'much']

for word_index in range(len(word_list)) :
    index_dict[word_list[word_index]].append(word_index)

word_index_to_find = 'foo'       
print(index_dict[word_index_to_find])

# output :  [0, 5]

-1

ในความคิดของฉัน["foo", "bar", "baz"].index("bar")เป็นสิ่งที่ดี แต่ก็ไม่พอเพราะถ้า "บาร์" ไม่ได้อยู่ในพจนานุกรมValueErrorยกดังนั้นคุณสามารถใช้ฟังก์ชั่นนี้:

def find_index(arr, name):
    try:
        return arr.index(name)
    except ValueError:
        return -1

if __name__ == '__main__':
    print(find_index(["foo", "bar", "baz"], "bar"))

และผลลัพธ์คือ:

1

และถ้าชื่อไม่ได้อยู่ที่ arr ฟังก์ชันจะส่งคืน -1 เช่น

พิมพ์ (find_index (["foo", "bar", "baz"], "fooo"))

-1


1
อย่าใช้นี้เพราะl = [1, 2]; find_index(l, 3)จะกลับมา-1และจะกลับมาl[find_index(l, 3)] 2-1 เป็นสิ่งที่ไม่ดีที่จะกลับมาเพียงแค่กลับไม่มี
Daniel Stracaboško

-1 คือสัญญาที่คุณสามารถคืนสิ่งที่คุณต้องการได้ แต่ลองใช้ Lesser None ในโปรแกรมของคุณเพราะ None หรือ Null ในการสื่อสารโปรแกรมของคุณกับโปรแกรมอื่น ๆ เช่นเว็บไซต์ android และ PHP อาจทำให้โปรแกรมหยุดตัวอย่างเช่นคุณอาจส่งคืน null ใน JSON และแอปพลิเคชันโทรศัพท์เว็บไซต์ของคุณจะปิดหรือส่งคืนข้อผิดพลาด 500 (ข้อผิดพลาดเซิร์ฟเวอร์ภายใน)
NaabNuts
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.