จะหาองค์ประกอบทั้งหมดในรายการได้อย่างไร?


378

index()จะให้การเกิดขึ้นครั้งแรกของรายการในรายการ มีเคล็ดลับเรียบร้อยที่ส่งกลับดัชนีทั้งหมดในรายการหรือไม่?


1
ฉันรู้สึกสับสนเล็กน้อยกับคำถามนี้: คุณต้องการค้นหารายการซ้ำในทุกระดับของรายการหลายมิติหรือคุณต้องการค้นหาสิ่งที่เกิดขึ้นในระดับบนสุดของรายการหรือไม่
Anderson Green

22
ในความคิดของฉันควรจะมีวิธีการรายการซึ่งทำสิ่งนี้
otocan

คำตอบ:


545

คุณสามารถใช้ list comprehension:

indices = [i for i, x in enumerate(my_list) if x == "whatever"]

3
สำหรับงูเหลือมรุ่นเก่าใช้ filter () สำหรับการใช้งานแบบเดียวกัน
Gleno

44
รายการความเข้าใจปรากฏตัวในหลามที่ 2.0, enumerateที่ 2.3 filter()ดังนั้นใช่ถ้าคุณหลามโบราณใช้
Steven Rumbalski

2
เทคนิคนี้จะไม่พบรายการทั้งหมดในอาร์เรย์หลายมิติ ตัวอย่างเช่นprint([i for i, x in enumerate([[1,1],[0,1]]) if x == 1])ผลตอบแทนแทน[] [[0, 1], [0, 0], [1, 1]]
Anderson Green

10
@AndersonGreen: คำว่า "อาร์เรย์หลายมิติ" แนะนำโครงสร้างข้อมูลที่รับประกันว่ามีขนาดสม่ำเสมอตามแต่ละแกน ไม่มีโครงสร้างข้อมูลดังกล่าวใน Python ธรรมดา มีรายการหลายรายการ แต่แตกต่างจาก "อาร์เรย์หลายมิติ" มาก หากคุณต้องการหลังคุณควรพิจารณาการใช้ NumPy ซึ่งช่วยให้คุณทำสิ่งที่ต้องการสำหรับอาร์เรย์(a == 1).nonzero() NumPy a
Sven Marnach

2
@MadmanLee หากคุณต้องการสิ่งที่รวดเร็วให้ใช้ NumPy ดูคำตอบของJoshAdel
Georgy

117

ในขณะที่ไม่ใช่วิธีแก้ปัญหาสำหรับรายการโดยตรงnumpyส่องสว่างสำหรับสิ่งนี้:

import numpy as np
values = np.array([1,2,3,1,2,4,5,6,3,2,1])
searchval = 3
ii = np.where(values == searchval)[0]

ผลตอบแทน:

ii ==>array([2, 8])

สิ่งนี้จะเร็วขึ้นอย่างมากสำหรับรายการ (อาร์เรย์) ที่มีองค์ประกอบจำนวนมากเทียบกับโซลูชันอื่น ๆ


2
ฉันสังเกตเห็นว่า [0] ในตอนท้ายแปลงสิ่งที่จะเป็นอาร์เรย์เป็นสตริง ฉันอยากรู้ว่าทำไมคุณเลือกที่จะทำ
amelia

5
[0]จำเป็นต้องมี@amelia 'เพราะwhereจะให้ผลตอบแทนเป็น tuple(array([2, 8], dtype=int64),)
Winand

1
เฮ้ @ ฉันชนะฉันใส่ [0] แต่ยังได้ทั้งสองส่วน นี่คือรหัสของฉัน: (nrg.local_logs.all_id_resp_address เป็นรายการ) "ste =" 199.38.164.165 "value = np.where (nrg.local_logs.all_id_resp_address == ste) [0]" ฉันในสิ่งที่ฉันทำผิด
Tomer

2
@Tomer แรกของทุกคนall_id_resp_addressควรจะได้np.array list
Winand

1
@Tomer คุณพยายามที่จะเปรียบเทียบlistและstrเห็นได้ชัดว่าคุณผ่านไปFalse np.whereเมื่อคุณเปรียบเทียบnp.arrayกับ smth คุณได้รับอาร์เรย์ของค่าบูลีน จากนั้นnp.whereค้นหาตำแหน่งของTrueค่าทั้งหมดของอาร์เรย์นั้น
Winand

29

วิธีใช้list.index:

def indices(lst, element):
    result = []
    offset = -1
    while True:
        try:
            offset = lst.index(element, offset+1)
        except ValueError:
            return result
        result.append(offset)

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

หมายเหตุ:หมายเหตุข้อควรระวังตามความคิดเห็นของ Chris_Rands: วิธีนี้เร็วกว่าความเข้าใจในรายการหากผลลัพธ์กระจัดกระจายเพียงพอ แต่ถ้ารายการมีองค์ประกอบหลายอย่างที่กำลังค้นหา (มากกว่า 15% ของรายการ) ในการทดสอบที่มีรายการ 1,000 จำนวนเต็ม) ความเข้าใจในรายการจะเร็วขึ้น


3
คุณบอกว่านี่เร็วกว่ารายการคอมพ์คุณสามารถแสดงเวลาที่แสดงให้เห็นได้หรือไม่?
Chris_Rands

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



8

more_itertools.locate ค้นหาดัชนีสำหรับรายการทั้งหมดที่ตรงตามเงื่อนไข

from more_itertools import locate


list(locate([0, 1, 1, 0, 1, 0, 0]))
# [1, 2, 4]

list(locate(['a', 'b', 'c', 'b'], lambda x: x == 'b'))
# [1, 3]

more_itertools> pip install more_itertoolsเป็นห้องสมุดของบุคคลที่สาม


1
อาจจะดีถ้า lib นี้ถูกเพิ่มไปยัง conda-forge (แม้ว่าจะconda installมีการเปิดใช้งานที่ไม่เสถียรในการทำงานเมื่อเร็ว ๆ นี้)
4651

4

อีกหนึ่งวิธีการแก้ปัญหา (ขออภัยถ้าซ้ำซ้อน) สำหรับเหตุการณ์ทั้งหมด:

values = [1,2,3,1,2,4,5,6,3,2,1]
map(lambda val: (val, [i for i in xrange(len(values)) if values[i] == val]), values)

4

หรือใช้range(python 3):

l=[i for i in range(len(lst)) if lst[i]=='something...']

สำหรับ (python 2):

l=[i for i in xrange(len(lst)) if lst[i]=='something...']

แล้ว (ทั้งสองกรณี):

print(l)

เป็นไปตามที่คาดไว้


4

ใช้ตัวกรอง () ใน python2

>>> q = ['Yeehaw', 'Yeehaw', 'Googol', 'B9', 'Googol', 'NSM', 'B9', 'NSM', 'Dont Ask', 'Googol']
>>> filter(lambda i: q[i]=="Googol", range(len(q)))
[2, 4, 9]

2

คุณสามารถสร้างคำสั่งเริ่มต้น

from collections import defaultdict
d1 = defaultdict(int)      # defaults to 0 values for keys
unq = set(lst1)              # lst1 = [1, 2, 2, 3, 4, 1, 2, 7]
for each in unq:
      d1[each] = lst1.count(each)
else:
      print(d1)

2

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

ด้วยการแจกแจง (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

คำตอบนี้ง่ายที่สุดสำหรับฉันที่จะใช้ในรหัสที่มีอยู่ของฉัน
Ryan Harris

2

ใช้for-loop:

  • คำตอบที่มีenumerateและรายการความเข้าใจมีประสิทธิภาพมากขึ้นและ pythonic อย่างไรก็ตามคำตอบนี้มีวัตถุประสงค์เพื่อนักเรียนที่อาจไม่ได้รับอนุญาตให้ใช้ฟังก์ชั่นในตัวบางอย่าง
  • สร้างรายการว่าง indices
  • สร้างการวนซ้ำด้วยfor i in range(len(x)):ซึ่งจะวนซ้ำตามรายการของตำแหน่งดัชนี[0, 1, 2, 3, ..., len(x)-1]
  • ในวงเพิ่มใด ๆiที่x[i]เป็นคู่ที่จะvalueไปindices
def get_indices(x: list, value: int) -> list:
    indices = list()
    for i in range(len(x)):
        if x[i] == value:
            indices.append(i)
    return indices

n = [1, 2, 3, -50, -60, 0, 6, 9, -60, -60]
print(get_indices(n, -60))

>>> [4, 8, 9]
  • ฟังก์ชั่นที่get_indicesมีการดำเนินการกับคำแนะนำประเภท ในกรณีนี้รายการnเป็นพวงของints ดังนั้นเราจึงค้นหายังกำหนดให้เป็นvalueint

ใช้while-loopและ.index:

def get_indices(x: list, value: int) -> list:
    indices = list()
    i = 0
    while True:
        try:
            # find an occurrence of value and update i to that index
            i = x.index(value, i)
            # add i to the list
            indices.append(i)
            # advance i by 1
            i += 1
        except ValueError as e:
            break
    return indices

print(get_indices(n, -60))
>>> [4, 8, 9]

การกำหนดตนเองของคุณget_indeicesจะเร็วกว่า (15%) เล็กน้อยกว่าความเข้าใจในรายการปกติ ฉันพยายามคิดออก
เทรวิส

1

หากคุณใช้ Python 2 คุณสามารถใช้ฟังก์ชันนี้ได้:

f = lambda my_list, value:filter(lambda x: my_list[x] == value, range(len(my_list)))

my_listรายการที่คุณต้องการรับดัชนีอยู่ที่ไหนและvalueเป็นค่าการค้นหา การใช้งาน:

f(some_list, some_element)

1

หากคุณต้องการค้นหาตำแหน่งขององค์ประกอบทั้งหมดระหว่างดัชนีบางอย่างคุณสามารถระบุ:

[i for i,x in enumerate([1,2,3,2]) if x==2 & 2<= i <=3] # -> [3]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.