2010-04-30 50 views
16

Python的列表类型有一个索引(x)方法。它使用单个参数x,并返回列表中具有值x的第一个项目的(整数)索引。在Python中,如何才能找到列表中第一个项目的索引不是某个值?

基本上,我需要反转索引(x)的方法。我需要得到没有值x的列表中第一个值的索引。我可能甚至可以使用一个函数返回值为!= None的第一个项目的索引。

我可以想到一个'for'循环实现与增量计数器变量,但我觉得我失去了一些东西。有没有一种现有的方法,或者一个可以处理这个问题的单线Python结构?

在我的程序中,当我处理从复杂正则表达式匹配返回的列表时,出现这种情况。每个列表中除了一个项目之外的所有项目的值均为无。如果我只是需要匹配的字符串,我可以使用列表理解,如'[x for [my_list],如果x不是None]',但我需要索引来确定我的正则表达式中的哪个捕获组实际上是由比赛。

+0

您确定需要索引而不是实际值吗? – 2010-04-30 23:42:09

+0

列表理解与for循环基本相同,但以不同的方式编写(通常很难阅读)。我建议只使用for循环,不管(与枚举) – mathmike 2010-04-30 23:43:54

回答

18

在第一场比赛退出只是利用是很容易的:不是计算一个完整的列表理解(然后扔掉除第一个项目之外的所有东西),在基因xp上使用next。例如假设你想-1在没有项目满足在!= x条件,

return next((i for i, v in enumerate(L) if v != x), -1) 

这是Python 2.6中的语法;如果你坚持2.5或更低版本,.next()是genexp(或其他迭代器)的一种方法,不接受默认值,如上面的-1(所以如果你不想看到StopIteration异常,你会必须使用try/except)。但是,那么之所以更多的发布是在2.5版之后发布的 - 语言及其内置插件的持续改进! - )

+0

我实际上不需要处理“不符合条件”条件,因为regex方法总是返回至少一个非无列表项。所以我认为这应该工作:next(如果x不是None,我为i,x在枚举(my_list)中)。在调试器下,它似乎停止在第一场比赛,所以我卖了。酷招。 – 2010-05-03 15:00:09

+0

@Ryan,是的,如果当所有项目都是None时不需要默认结果,那么简单的表达式就可以正常工作。 – 2010-05-03 16:58:33

4

enumerate()返回一个迭代器,该迭代器产生可迭代当前索引的元组以及项目本身。

+1

唉,我真的错过了一些东西。是的,确切的用法是这样的:[我为我,x在枚举(my_list)如果x不是无]。谢谢! – 2010-04-30 23:38:29

1
[i for i, x in enumerate(my_list) if x != value][0] 

如果你不能确定是否有不匹配的项目,而不是使用:

match = [i for i, x in enumerate(my_list) if x != value] 
if match: 
    i = match[0] 
    # i is your number. 

可以让这个更“实用”与itertools,但你很快就会到达指出一个简单的for循环更好。即使上述解决方案的效率也不如for循环,因为它们会在您引起兴趣之前构建所有不匹配索引的列表。

5

当你只需要第一个时,使用列表理解只是感觉粘糊糊(对我)。使用for循环并尽早退出。

>>> lst = [None, None, None, "foo", None] 
>>> for i, item in enumerate(lst): 
... if item: break 
... else: 
... print "not found" 
... 
>>> i 
3 
+0

你读过我原来的问题中的第3段了吗? for循环的实现是微不足道的。我特意寻找单线或现有的方法。 (根据选票,似乎你并不是唯一一个错过了这个观点的人,我应该让它更加明显一点。) – 2010-05-04 16:47:27

+0

@Ryan B. Lynch:我确实读到过。你提到你可以使用for-loop和counter ......这是更多的代码,并且有点难看。我使用枚举()来自动获取计数器。从你的问题,我不确定你是否知道枚举存在。 OTOH,我不知道next()是否存在(但我持续使用Python 2.5),所以我从Alex的解决方案中学到了一些东西。我不知道为什么人们投票赞成这个,也许这些选票是来自尝试用一句话来做的事情,这些事情可以轻而易举地透明地在两个方面完成。 – Stephen 2010-05-04 17:42:13

+0

关于柜台与破坏事物的好处。至于关于“试图用一句话来做一些可以平淡而透明地做两件事的事情”的观点,你的原始答案很清楚地表达了它的意思。但是,如果编码风格的考虑激发你的回应,为什么要把它作为答案呢?这不是什么意见? – 2010-05-04 19:55:43

0

是一个愚蠢的基础itertools解决方案:)

import itertools as it, operator as op, functools as ft 

def index_ne(item, sequence): 
    sequence= iter(sequence) 
    counter= it.count(-1) # start counting at -1 
    pairs= it.izip(sequence, counter) # pair them 
    get_1st= it.imap(op.itemgetter(0), pairs) # drop the used counter value 
    ne_scanner= it.ifilter(ft.partial(op.ne, item), get_1st) # get only not-equals 
    try: 
     ne_scanner.next() # this should be the first not equal 
    except StopIteration: 
     return None # or raise some exception, all items equal to item 
    else: 
     return counter.next() # should be the index of the not-equal item 

if __name__ == "__main__": 
    import random 

    test_data= [0]*20 
    print "failure", index_ne(0, test_data) 

    index= random.randrange(len(test_data)) 
    test_data[index]= 1 
    print "success:", index_ne(0, test_data), "should be", index 

这一切的itertools.count计数:)

+0

请注意,在某些情况下,可以使用'item .__ ne__'来代替上面的'ft.partial(op.ne,item)'设备;然而,后者适用于所有'项目'。 – tzot 2010-05-01 00:49:33

+4

这令人印象深刻难以理解。 – 2010-05-01 00:59:21

相关问题