返回列表中第一个元素的索引,该元素使传递的函数为真

2025-03-18 08:54:00
admin
原创
48
摘要:问题描述:该list.index(x)函数返回列表中第一个值为 的项目的索引x。是否有一个函数list_func_index(),类似于index()具有函数f()作为参数的函数。函数对列表的 f()每个元素 运行,直到返回。然后返回 的索引。e`f(e)Truelist_func_index()`e代码方面...

问题描述:

list.index(x)函数返回列表中第一个值为 的项目的索引x

是否有一个函数list_func_index(),类似于index()具有函数f()作为参数的函数。函数对列表的 f()每个元素 运行,直到返回。然后返回 的索引。e`f(e)Truelist_func_index()`e

代码方面:

>>> def list_func_index(lst, func):
      for i in range(len(lst)):
        if func(lst[i]):
          return i
      raise ValueError('no element making func True')

>>> l = [8,10,4,5,7]
>>> def is_odd(x): return x % 2 != 0
>>> list_func_index(l,is_odd)
3

有没有更优雅的解决方案?(以及更好的函数名称)


解决方案 1:

您可以使用生成器在一行中完成此操作:

next(i for i,v in enumerate(l) if is_odd(v))

生成器的优点在于它们只计算请求的数量。因此请求前两个索引(几乎)同样简单:

y = (i for i,v in enumerate(l) if is_odd(v))
x1 = next(y)
x2 = next(y)

不过,在最后一个索引之后会出现 StopIteration 异常(这就是生成器的工作方式)。这在“先取”方法中也很方便,可以知道没有找到这样的值 ---list.index()函数会ValueError在此处引发。

解决方案 2:

一种可能性是内置的枚举函数:

def index_of_first(lst, pred):
    for i, v in enumerate(lst):
        if pred(v):
            return i
    return None

通常将您描述的函数称为“谓词”;它会针对某些问题返回 true 或 false。这就是我pred在示例中这样称呼它的原因。

我还认为返回 会更好None,因为这是问题的真正答案。None如果需要,调用者可以选择在 上展开。

解决方案 3:

保罗接受的答案是最好的,但这里有一个小小的横向思维变体,主要是为了娱乐和指导目的......:

>>> class X(object):
...   def __init__(self, pred): self.pred = pred
...   def __eq__(self, other): return self.pred(other)
... 
>>> l = [8,10,4,5,7]
>>> def is_odd(x): return x % 2 != 0
... 
>>> l.index(X(is_odd))
3

本质上,X的目的是将“相等”的含义从正常含义更改为“满足此谓词”,从而允许在定义为检查相等性的各种情况下使用谓词 - 例如,它还允许您编写if any(is_odd(x) for x in l):更短的而不是if X(is_odd) in l:,等等。

值得使用吗?当 @Paul 所采用的更明确的方法同样方便时(尤其是当更改为使用新的、闪亮的内置next函数而不是旧的、不太合适的.next方法时,正如我在该答案的评论中所建议的那样),但还有其他情况下它(或“调整相等的含义”这一想法的其他变体,也许还有其他比较器和/或散列)可能是合适的。最重要的是,值得了解这个想法,以避免有一天不得不从头开始发明它。

解决方案 4:

虽然不是一个单一的函数,但是你可以在 Python 2 中很容易地做到这一点:

>>> test = lambda c: c == 'x'
>>> data = ['a', 'b', 'c', 'x', 'y', 'z', 'x']
>>> map(test, data).index(True)
3

如果您不想一次评估整个列表,您可以使用 itertools,但它不太漂亮:

>>> from itertools import imap, ifilter
>>> from operator import itemgetter
>>> ifilter(itemgetter(1), enumerate(imap(test, data))).next()[0]
3

尽管仅使用生成器表达式可能更具可读性itertools

请注意在 Python3 中,map返回filter惰性迭代器,您只需使用:

>>> from operator import itemgetter
>>> next(filter(itemgetter(1), enumerate(map(test, data))))[0]
3

解决方案 5:

Alex 的答案的变体。这样就避免了X每次要使用is_odd或任何谓词时都必须键入

>>> class X(object):
...     def __init__(self, pred): self.pred = pred
...     def __eq__(self, other): return self.pred(other)
... 
>>> L = [8,10,4,5,7]
>>> is_odd = X(lambda x: x%2 != 0)
>>> L.index(is_odd)
3
>>> less_than_six = X(lambda x: x<6)
>>> L.index(less_than_six)
2

解决方案 6:

直观的单行解决方案:

i = list(map(lambda value: value > 0, data)).index(True)

解释:

  1. 我们使用 map 函数创建一个包含 True 或 False 的迭代器,具体取决于列表中的每个元素是否符合 lambda 中的条件。

  2. 然后我们将地图输出转换为列表

  3. 然后使用索引函数,我们得到第一个真的索引,它与通过条件的第一个值的索引相同。

解决方案 7:

使用一些我最喜欢的、值得更多喜爱的工具(indexOf,,compresscount

from operator import indexOf

def list_func_index(lst, func):
    return indexOf(map(func, lst), True)
from itertools import compress, count

def list_func_index(lst, func):
    return next(compress(count(), map(func, lst)))

或者与你的ValueError

from itertools import compress, count

def list_func_index(lst, func):
    for index in compress(count(), map(func, lst)):
        return index
    raise ValueError('no element making func True')
ist_func_index(l, is_odd))

在线尝试!

解决方案 8:

这是一个 python3 答案,旨在体现 any() 和 all() 的精神:

def index(iterable, desired_item=True):
  for i,item in enumerate(iterable):
    if item == desired_item:
      return i
  raise ValueError(f"no {desired_item} in iterable")

>>> any(n!=0 and n%6==0 and n%15==0 for n in range(10**100))
True
>>> all(n!=0 and n%6==0 and n%15==0 for n in range(10**100))
False
>>> index(n!=0 and n%6==0 and n%15==0 for n in range(10**100))
30

使用OP的示例:

>>> l = [8,10,4,5,7]
>>> def is_odd(x): return x % 2 != 0

>>> any(is_odd(x) for x in l)
True
>>> all(is_odd(x) for x in l)
False
>>> index(is_odd(x) for x in l)
3

注意:尽管我通常不喜欢默认参数,但我还是添加了可选desired_item参数,这只是为了减轻使用名称的负罪感index;这使得它对于那些认为该函数可以像下面这样使用的人来说很有用(因为他们熟悉index许多语言中调用的其他函数,包括listpython 中的成员函数):

>>> index((2*n for n in range(googol)), 20)
10

解决方案 9:

你可以用列表理解来做到这一点:

l = [8,10,4,5,7]
filterl = [a for a in l if a % 2 != 0]

然后 filterl 将返回满足表达式 a % 2 != 0 的列表中的所有成员。我想说一种更优雅的方法......

相关推荐
  政府信创国产化的10大政策解读一、信创国产化的背景与意义信创国产化,即信息技术应用创新国产化,是当前中国信息技术领域的一个重要发展方向。其核心在于通过自主研发和创新,实现信息技术应用的自主可控,减少对外部技术的依赖,并规避潜在的技术制裁和风险。随着全球信息技术竞争的加剧,以及某些国家对中国在科技领域的打压,信创国产化显...
工程项目管理   2482  
  为什么项目管理通常仍然耗时且低效?您是否还在反复更新电子表格、淹没在便利贴中并参加每周更新会议?这确实是耗费时间和精力。借助软件工具的帮助,您可以一目了然地全面了解您的项目。如今,国内外有足够多优秀的项目管理软件可以帮助您掌控每个项目。什么是项目管理软件?项目管理软件是广泛行业用于项目规划、资源分配和调度的软件。它使项...
项目管理软件   1533  
  PLM(产品生命周期管理)项目对于企业优化产品研发流程、提升产品质量以及增强市场竞争力具有至关重要的意义。然而,在项目推进过程中,范围蔓延是一个常见且棘手的问题,它可能导致项目进度延迟、成本超支以及质量下降等一系列不良后果。因此,有效避免PLM项目范围蔓延成为项目成功的关键因素之一。以下将详细阐述三大管控策略,助力企业...
plm系统   0  
  PLM(产品生命周期管理)项目管理在企业产品研发与管理过程中扮演着至关重要的角色。随着市场竞争的加剧和产品复杂度的提升,PLM项目面临着诸多风险。准确量化风险优先级并采取有效措施应对,是确保项目成功的关键。五维评估矩阵作为一种有效的风险评估工具,能帮助项目管理者全面、系统地评估风险,为决策提供有力支持。五维评估矩阵概述...
免费plm软件   0  
  引言PLM(产品生命周期管理)开发流程对于企业产品的全生命周期管控至关重要。它涵盖了从产品概念设计到退役的各个阶段,直接影响着产品质量、开发周期以及企业的市场竞争力。在当今快速发展的科技环境下,客户对产品质量的要求日益提高,市场竞争也愈发激烈,这就使得优化PLM开发流程成为企业的必然选择。缺陷管理工具和六西格玛方法作为...
plm产品全生命周期管理   0  
热门文章
项目管理软件有哪些?
曾咪二维码

扫码咨询,免费领取项目管理大礼包!

云禅道AD
禅道项目管理软件

云端的项目管理软件

尊享禅道项目软件收费版功能

无需维护,随时随地协同办公

内置subversion和git源码管理

每天备份,随时转为私有部署

免费试用