remove 在Python中查找包含它的列表的項目索引




python list教學 (23)

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

參考: 數據結構>更多列表

警告如下

請注意,儘管這可能是回答問題的最簡潔方法,但indexlist API的一個相當弱的組件,我不記得上次我在憤怒中使用它了。 在評論中已經向我指出,因為這個答案被大量引用,所以應該更加完整。 關於list.index一些警告如下。 最初可能需要查看文檔字符串:

>>> print(list.index.__doc__)
L.index(value, [start, [stop]]) -> integer -- return first index of value.
Raises ValueError if the value is not present.

列表長度的線性時間複雜度

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的調用按順序搜索列表,直到找到匹配項,然後停在那裡。 如果您希望需要更多匹配的索引,則應使用列表推導或生成器表達式。

>>> [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 (可能更快,至少當搜索列表很長時,該項通常存在。)

對於列表["foo", "bar", "baz"]和列表"bar" ,如何在Python中獲取其索引(1)?


大多數答案解釋瞭如何查找單個索引 ,但如果項目在列表中多次,則它們的方法不會返回多個索引。 使用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

如果表現令人擔憂:

在許多答案中提到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]

如果列表沒有您需要檢查索引的重複項,則有兩種可能性

 eg: li=[10,20,30] # here need to get index of 20 means
     li.index(20) # will work properly because 20 is not repeated

如果它的重複意味著它只會給你第一個索引

如果您需要獲取項目所在的所有索引,則表示

eg: li=[10,20,30,20,40, 50, 10] # here need to get index of 20 means its have 2 index (1,3) 

得到你需要這樣做

 li=[10,20,30,20,40, 50, 10]
 [i for i, e in enumerate(li) if e == 20]

然後你會得到一個索引列表為o / p,如[1,3]


具有zip功能的所有索引:

get_indexes = lambda x, xs: [i for (y, i) in zip(xs, range(len(xs))) if x == y]

print get_indexes(2, [1, 2, 3, 4, 5, 6, 3, 2, 3, 2])
print get_indexes('f', 'xsfhhttytffsafweef')

獲取列表中一個或多個(相同)項的所有出現次數和位置

使用enumerate(alist),當元素x等於您查找的內容時,您可以存儲第一個元素(n),它是列表的索引。

>>> 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

在Python中查找包含它的列表的項目索引

對於列表["foo", "bar", "baz"]和列表"bar"的項目,在Python中獲取其索引(1)的最簡潔方法是什麼?

嗯,當然,有索引方法,它返回第一次出現的索引:

>>> 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 None:

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)

更好的數據與熊貓交配

如果您有pandas,可以使用Series對象輕鬆獲取此信息:

>>> 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

通過下標符號將該系列布爾值傳遞給系列,您只得到匹配的成員:

>>> 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]

是的,你也可以使用枚舉的列表理解,但是在我看來,這不是那麼優雅 - 你在Python中進行相等的測試,而不是讓用C編寫的內置代碼處理它:

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

這是XY問題嗎?

XY問題是詢問您嘗試的解決方案而不是實際問題。

為什麼你認為你需要給定列表中的元素的索引?

如果您已經知道該值,為什麼要關注它在列表中的位置?

如果值不存在,捕獲ValueError相當冗長 - 我寧願避免這種情況。

我通常會在列表上進行迭代,所以我通常會指向任何有趣的信息,並使用枚舉來獲取索引。

如果您正在調整數據,那麼您應該使用pandas - 它擁有比我所展示的純Python工作區更優雅的工具。

我不記得需要list.index ,我自己。 但是,我查看了Python標準庫,我發現它有一些很好的用途。

idlelib有很多很多用途,用於GUI和文本解析。

keyword模塊使用它來查找模塊中的註釋標記,以通過元編程自動重新生成其中的關鍵字列表。

在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)

這些用法似乎有共同之處在於它們似乎在約束大小的列表上運行(因為list.index的O(n)查找時間很重要),並且它們主要用於解析(以及用於解析的UI)閒)。

雖然有用例,但它們並不常見。 如果您發現自己正在尋找這個答案,那麼問問自己,您所做的事情是否是最直接使用該語言為您的用例提供的工具。


由於Python列表從零開始,我們可以使用zip內置函數,如下所示:

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

其中“haystack”是有問題的列表,“needle”是要查找的項目。

(注意:這裡我們使用i來迭代獲取索引,但如果我們需要關注項目,我們可以切換到j。)


index()返回第一個值的索引!

| 指數(...)
| L.index(value,[start,[stop]]) - > integer - 返回第一個值的索引

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"])

a = ["foo","bar","baz",'bar','any','much']

indexes = [index for index in range(len(a)) if a[index] == 'bar']

這個解決方案沒有其他解決方案那麼強大,但是如果你是初學者並且只知道for循環,那麼仍然可以找到項目的第一個索引,同時避免使用ValueError:

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

您必須設置條件以檢查您要搜索的元素是否在列表中

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

對此有一個更實用的答案。

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))))))

你可以隨便去

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

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

對於那些來自像我這樣的其他語言的人來說,也許通過一個簡單的循環,它更容易理解和使用它:

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

我很感謝所以枚舉到底是做什麼的? 。 這讓我明白了。


獲取所有索引:

 indexes = [i for i,x in enumerate(xs) if x == 'foo']

學習Python真正有用的一件事是使用交互式幫助功能:

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

class list(object)
 ...

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

這通常會引導您找到您正在尋找的方法。


這裡提出的所有函數都重現了固有的語言行為,但卻模糊了正在發生的事情。

[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

如果語言提供了自己想做的方法,為什麼要編寫一個帶異常處理的函數?


如果找不到該項,Python index()方法會拋出錯誤,這很糟糕!

所以你可以使它類似於JavaScript的indexOf()函數,如果找不到該項,則返回-1

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

而現在,對於完全不同的東西......

...比如在獲得索引之前確認項目的存在。 這種方法的好處是函數總是返回一個索引列表 - 即使它是一個空列表。 它也適用於字符串。

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窗口時:

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]
>>> 

更新

經過另一年的低調python開發,我對我的原始答案感到有點尷尬,所以為了直接設置記錄,你當然可以使用上面的代碼; 然而,獲得相同行為的更慣用的方法是使用列表理解以及enumerate()函數。

像這樣的東西:

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窗口時產生:

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]
>>> 

現在,在回顧了這個問題和所有答案之後,我意識到這正是在他之前的回答中所建議的。 當我最初回答這個問題時,我甚至沒有看到答案,因為我不明白。 我希望我的一些更冗長的例子能夠幫助理解。

如果上面的單行代碼對您沒有意義,我強烈建議您使用Google'python list comprehension'並花幾分鐘時間熟悉自己。 它只是使用Python開發代碼的許多強大功能之一。


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


來自FMc和user7177的答案的變體將給出一個可以返回任何條目的所有索引的dict:

>>> 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)來減少lambda被調用的次數,但是效率沒有保證。


讓我們將名稱命名為lst到您擁有的列表中。 可以將列表lst轉換為numpy array 。 然後,使用numpy.where獲取列表中所選項的索引。 以下是您實施它的方式。

 import numpy as np lst = ["foo", "bar", "baz"] #lst: : 'list' data type lst_np = np.array(lst) #lst_np: 'numpy.ndarray' index = np.where( lst_np == 'bar')[0][0] #index: 'numpy.int64' data type print index 1 




list