提问人:Eugene M 提问时间:10/7/2008 最后编辑:Mateen UlhaqEugene M 更新时间:10/28/2023 访问量:6155572
查找列表中项的索引
Finding the index of an item in a list
答:
>>> ["foo", "bar", "baz"].index("bar")
1
有关列表的内置方法,请参阅文档:.index()
list.index(x[, start[, end]])
在值等于 x 的第一项的列表中返回从零开始的索引。如果没有此类项,则引发
ValueError
。可选参数 start 和 end 被解释为切片表示法,用于将搜索限制为列表的特定子序列。返回的索引是相对于完整序列的开头计算的,而不是相对于开始参数计算的。
警告
列表长度的线性时间复杂度
调用按顺序检查列表的每个元素,直到找到匹配项。如果列表很长,并且不能保证该值将接近开头,则可能会减慢代码速度。index
这个问题只能通过使用不同的数据结构来完全避免。但是,如果已知元素位于列表的某个部分内,则可以使用 和 参数来缩小搜索范围。start
end
例如:
>>> 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
第二个调用的速度要快几个数量级,因为它只需要搜索 10 个元素,而不是全部 100 万个元素。
仅返回第一个匹配项的索引
按顺序搜索列表,直到找到匹配项,然后停止的调用。如果该值可能出现多个,并且需要所有索引,则无法解决问题:index
index
>>> [1, 1].index(1) # the `1` index is not found.
0
相反,使用列表推导式或生成器表达式进行搜索,并使用枚举
来获取索引:
>>> # A list comprehension gives a list of indices directly:
>>> [i for i, e in enumerate([1, 2, 1]) if e == 1]
[0, 2]
>>> # A generator comprehension gives us an iterable object...
>>> g = (i for i, e in enumerate([1, 2, 1]) if e == 1)
>>> # which can be used in a `for` loop, or manually iterated with `next`:
>>> next(g)
0
>>> next(g)
2
如果只有一个匹配项,列表推导和生成器表达式技术仍然有效,并且更通用。
如果没有匹配项,则引发异常
如上面的文档中所述,如果搜索的值不在列表中,using 将引发异常:.index
>>> [1, 1].index(2)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: 2 is not in list
如果这是一个问题,请先使用 显式检查,或根据需要使用 / 处理异常。item in my_list
try
except
显式检查简单易读,但它必须再次迭代列表。有关此选择的更多指导,请参阅 Python 中的 EAFP 原则是什么?
评论
index()
index()
返回第一个 value 索引!
|索引(...)
|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']
如果该元素不在列表中,则会出现问题。此函数处理以下问题:
# 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
这里提出的所有函数都重现了固有的语言行为,但模糊了正在发生的事情。
[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
如果语言提供了执行您想要执行的操作的方法,为什么还要编写具有异常处理功能的函数?
评论
简单地说,你可以
a = [['hand', 'head'], ['phone', 'wallet'], ['lost', 'stock']]
b = ['phone', 'lost']
res = [[x[0] for x in a].index(y) for y in b]
另一种选择
>>> a = ['red', 'blue', 'green', 'red']
>>> b = 'red'
>>> offset = 0;
>>> indices = list()
>>> for i in range(a.count(b)):
... indices.append(a.index(b,offset))
... offset = indices[-1]+1
...
>>> indices
[0, 3]
>>>
评论
大多数答案解释了如何查找单个索引,但如果项目多次出现在列表中,则其方法不会返回多个索引。使用 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()
的小解决方案(这与 enumerate 的方法几乎相同):
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
评论
if len([i for i, j in enumerate(['foo', 'bar', 'baz']) if j == 'bar']) > 1
[i for i, j in enumerate(['foo', 'bar', 'baz']) if j == 'bar'][0]
要获取所有索引,请执行以下操作:
indexes = [i for i, x in enumerate(xs) if x == 'foo']
评论
来自 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) 来减少调用 lambda 的次数,但无法保证效率。
评论
您必须设置一个条件来检查您正在搜索的元素是否在列表中
if 'your_element' in mylist:
print mylist.index('your_element')
else:
print None
评论
in
而现在,对于完全不同的东西......
...就像在获取索引之前确认项目的存在一样。这种方法的好处是函数总是返回一个索引列表——即使它是一个空列表。它也适用于字符串。
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]
>>>
现在,在回顾了这个问题和所有答案之后,我意识到这正是 FMc 在他之前的回答中建议的。在我最初回答这个问题的时候,我什至没有看到那个答案,因为我不明白。我希望我这个更冗长的例子将有助于理解。
如果上面的单行代码对你来说仍然没有意义,我强烈建议你谷歌“python列表推导”,并花几分钟时间熟悉一下。这只是众多强大的功能之一,使使用 Python 开发代码成为一种乐趣。
这个解决方案不如其他解决方案强大,但如果你是一个初学者,只知道循环,仍然可以找到一个项目的第一个索引,同时避免 ValueError:for
def find_element(p,t):
i = 0
for e in p:
if e == t:
return i
else:
i +=1
return -1
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
所有带有 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(xs)
比 更清晰。此外,这并不能回答这个问题。zip(xs, range(len(xs))
如果你想要所有索引,那么你可以使用 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),)
这是一个清晰、可读的解决方案。
评论
获取列表中一个或多个(相同)项的所有出现次数和位置
使用 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 列表是从零开始的,我们可以按如下方式使用 zip 内置函数:
>>> [i for i,j in zip(range(len(haystack)), haystack) if j == 'needle' ]
其中“Haystack”是有问题的列表,“Needle”是要查找的项目。
(注意:这里我们使用 i 来迭代获取索引,但如果我们需要专注于项目,我们可以切换到 j。
评论
在 Python 中查找给定包含它的列表的项目的索引
对于列表和列表中的项目,在 Python 中获取其索引 (1) 的最干净方法是什么?
["foo", "bar", "baz"]
"bar"
嗯,当然,有 index 方法,它返回第一次出现的索引:
>>> 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
这样做的缺点是,您可能会检查返回的值或 None: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)
更好地利用熊猫进行数据整理
如果你有 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 变通方法有更优雅的工具。
我不记得自己需要。但是,我已经浏览了 Python 标准库,我发现它有一些很好的用途。list.index
它在 、 GUI 和文本解析中有很多很多用途。idlelib
该模块使用它来查找模块中的注释标记,以通过元编程自动重新生成其中的关键字列表。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)
这些用法的共同点似乎是,它们似乎对受约束大小的列表进行操作(很重要,因为 的查找时间为 O(n),并且它们主要用于解析(在空闲的情况下使用 UI)。list.index
虽然它有用例,但它们相当罕见。如果你发现自己在寻找这个答案,问问自己,你正在做的是否是该语言为你的用例提供的工具的最直接使用。
对于那些像我这样来自其他语言的人来说,也许通过一个简单的循环更容易理解和使用它:
mylist = [
"foo", "bar",
"baz", "bar"
]
for index, item in enumerate(mylist):
if item == "bar":
print(index, item)
我很感谢 那么枚举到底是做什么的?这帮助我理解了。
评论
enumerate(mylist)
如果未找到该项,Python 方法将引发错误。因此,您可以使其类似于 JavaScript 的函数,如果未找到该项,则返回该函数:index()
indexOf()
-1
def indexof( array, elem):
try:
return array.index(elem)
except ValueError:
return -1
评论
对此有一个更实用的答案。
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))))))
评论
Scala
查找列表 L 中项目 x 的索引:
idx = L.index(x) if (x in L) else -1
评论
如果性能受到关注:
在许多答案中都提到,方法的内置方法是 O(n) 算法。如果您需要执行一次,这很好。但是,如果您需要多次访问元素的索引,则首先创建一个项目-索引对的字典 (O(n)),然后在每次需要时访问位于 O(1) 的索引会更有意义。list.index(item)
如果您确定列表中的项目永远不会重复,则可以轻松:
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]
正如@TerryA所指出的,许多答案都讨论了如何找到一个索引。
more_itertools
是一个第三方库,其中包含用于在可迭代对象中查找多个索引的工具。
鉴于
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
进行安装。
让我们为您拥有的列表命名。可以将列表转换为 .然后,使用 numpy.where 获取列表中所选项目的索引。以下是您将实现它的方式。lst
lst
numpy array
import numpy as np
lst = ["foo", "bar", "baz"] #lst: : 'list' data type
print np.where( np.array(lst) == 'bar')[0][0]
>>> 1
评论
使用字典,其中首先处理列表,然后向其添加索引
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]
如果您要查找一次索引,那么使用“索引”方法可以。但是,如果您要多次搜索数据,那么我建议使用 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
评论
对于一个可比的
# Throws ValueError if nothing is found
some_list = ['foo', 'bar', 'baz'].index('baz')
# some_list == 2
自定义谓词
some_list = [item1, item2, item3]
# Throws StopIteration if nothing is found
# *unless* you provide a second parameter to `next`
index_of_value_you_like = next(
i for i, item in enumerate(some_list)
if item.matches_your_criteria())
按谓词查找所有项的索引
index_of_staff_members = [
i for i, user in enumerate(users)
if user.is_staff()]
评论
idx = next((i for i, v in enumerate(ls) if v == chk), -1)
获取类似于 str.index(chk) 的行为。
该值可能不存在,因此为了避免此 ValueError,我们可以检查该值是否确实存在于列表中。
list = ["foo", "bar", "baz"]
item_to_find = "foo"
if item_to_find in list:
index = list.index(item_to_find)
print("Index of the item is " + str(index))
else:
print("That word does not exist")
评论
list
in
index
try
except
.index()
它只使用 python 函数,并使用简单的 Try / Except 如果在列表中找到记录,则返回记录的位置,如果在列表中找不到,则返回 -1(就像在 JavaScript 上使用函数一样)。array.index()
indexOf()
fruits = ['apple', 'banana', 'cherry']
try:
pos = fruits.index("mango")
except:
pos = -1
在这种情况下,“芒果”不在列表中,因此变量为 -1,如果我搜索“樱桃”,变量将为 2。fruits
pos
pos
简单的选项:
a = ["foo", "bar", "baz"]
[i for i in range(len(a)) if a[i].find("bar") != -1]
评论
我发现这两个解决方案更好,我自己尝试了
>>> expences = [2200, 2350, 2600, 2130, 2190]
>>> 2000 in expences
False
>>> expences.index(2200)
0
>>> expences.index(2350)
1
>>> index = expences.index(2350)
>>> expences[index]
2350
>>> try:
... print(expences.index(2100))
... except ValueError as e:
... print(e)
...
2100 is not in list
>>>
Pythonic 方式可以使用,但您也可以从模块中使用 indexOf
。请注意,如果 b
不在 a
中,这将引发 ValueError
。enumerate
operator
>>> from operator import indexOf
>>>
>>>
>>> help(indexOf)
Help on built-in function indexOf in module _operator:
indexOf(a, b, /)
Return the first index of b in a.
>>>
>>>
>>> indexOf(("foo", "bar", "baz"), "bar") # with tuple
1
>>> indexOf(["foo", "bar", "baz"], "bar") # with list
1
python 中的某些结构包含一个索引方法,可以很好地解决这个问题。
'oi tchau'.index('oi') # 0
['oi','tchau'].index('oi') # 0
('oi','tchau').index('oi') # 0
引用:
text = ["foo", "bar", "baz"]
target = "bar"
[index for index, value in enumerate(text) if value == target]
对于一小部分元素,这将正常工作。但是,如果 列表包含大量元素,最好应用二进制 使用 O(log n) 运行时复杂度进行搜索。
评论
下面是使用 Python 函数的两行代码:index()
LIST = ['foo' ,'boo', 'shoo']
print(LIST.index('boo'))
输出:1
列表推导是在查找列表中的项的索引时获得紧凑实现的最佳选择。
a_list = ["a", "b", "a"]
print([index for (index , item) in enumerate(a_list) if item == "a"])
评论
me = ["foo", "bar", "baz"]
me.index("bar")
您可以将此项应用于列表的任何成员以获取其索引
可以使用 zip() 函数来获取列表中值的索引。代码可以是;
list1 = ["foo","bar","baz"]
for index,value in zip(range(0,len(list1)),list1):
if value == "bar":
print(index)
评论
zip(range(0,len(list1)),list1)
当你可以做的时候,是矫枉过正enumerate(list1)
请尝试以下代码:
["foo", "bar", "baz"].index("bar")
参考:https://www.programiz.com/python-programming/methods/list/index
不要。如果绝对需要,请使用列表中的方法。然而,这需要线性时间,如果你发现自己伸手去拿它,你可能滥用列表来做一些你不应该用它们做的事情。.index(item...)
最有可能的是,您关心的是 1) 整数和项目之间的双向映射,或者 2) 在排序的项目列表中查找项目。
对于第一个,使用一对词典。如果您想要一个可以为您执行此操作的库,请使用该库。bidict
对于第二个,使用可以正确利用列表排序这一事实的方法。使用 python 中的内置模块。bisect
如果您发现自己想要在排序列表中插入项目,也不应使用排序列表。要么使用内置模块将排序需求弱化为堆,要么使用库。heapq
sortedcontainers
使用不是为您要执行的操作而设计的数据结构是一种不好的做法。使用与您赋予的任务相匹配的解决方案,既可以向读者传达您想要执行特定操作的信息,也可以使您的解决方案在实践中更快/更具可扩展性。
python 中的简单解决方案:
li1=["foo","bar","baz"]
for i in range(len(li1)):
if li1[i]=="bar":
print(i)
列表元素的数据类型无关紧要。只需将“bar”替换为您要查找的元素即可。我们也可以为此编写一个函数,如下所示:
def indexfinder(element,lis):
for i in range(len(lis)):
if lis[i]==element:
return i
令人惊讶的是,此评论中提到的 next
的回退值第二个参数尚未在此处显示。
当您可以比较整个对象时,基本功能效果很好,但通常需要通过某个属性搜索特定项目的对象或字典列表,在这种情况下,带有条件的生成器是自然的选择:.index()
>>> users = [{"id": 2, "name": "foo"}, {"id": 3, "name": "bar"}]
>>> target_id = 2
>>> found_user = next(x for x in users if x["id"] == target_id)
>>> found_user
{'id': 2, 'name': 'foo'}
这停在第一个匹配元素上,并且相当简洁。
但是,如果没有找到匹配的元素,则会引发错误,这有点尴尬。幸运的是,它提供了第二个参数回退,以提供更自然、更自由的控制流:StopIteration
next
next(gen, default)
except
>>> found_user = next((x for x in users if x["id"] == target_id), None)
>>> if not found_user:
... print("user not found")
...
user not found
这有点冗长,但仍然相当可读。
如果需要索引:
>>> found_idx = next((i for i, x in enumerate(users) if x["id"] == 1), None)
>>> found_idx
None
>>> next((i for i, x in enumerate(users) if x["id"] == 3), None)
1
正如此评论所指出的,最好不要为缺失的索引返回典型的 -1,因为这是 Python 中的有效索引。如果看起来很奇怪,提高是合适的。None
这些有点冗长,但如果您重复使用它,请随意将代码隐藏在帮助程序函数中,提供任意谓词。
>>> def find(it, pred):
... return next((x for x in it if pred(x)), None)
...
>>> find(users, lambda user: user["id"] == 2)
{'id': 2, 'name': 'foo'}
>>> print(find(users, lambda user: user["id"] == 42))
None
>>> find("foobAr", str.isupper) # works on any iterable!
'A'
在列表中查找元素索引的最简单方法之一是执行以下操作
arr = ["foo", "bar", "baz"]
el = "bar"
try:
index = arr.index(el)
return index
except:
return 'element not found'
类似于其他语言的函数“indexof”,如果找不到元素,则 returs -1 可以写成
def indexof (obj, elem, offset=0):
if elem in obj[offset:]:
return offset + obj[offset:].index(elem)
return -1
obj = ["foo", "bar", "baz", "foo"]
print (indexof(obj, "not here"))
print (indexof(obj, "baz"))
print (indexof(obj, "foo", 1))
返回
-1
2
3
或针对大列表的优化版本
def indexof (obj, elem, offset=0):
if offset == 0:
# no need of a sublist
if elem in obj:
return obj.index(elem)
return -1
sublist = obj[offset:]
if elem in sublist:
return offset + sublist.index(elem)
return -1
评论
"bar"
"bar"