Python在列表中search
我有两个列表的列表,需要search的东西。
如果列表是:
list =[ ['a','b'], ['a','c'], ['b','d'] ]
我可以很容易地search一对
['a','b'] in list
现在,有没有办法看看我是否有一个string出现在第二个位置? 我可以做这个:
for i in range (0, len(list)): if list[i][1]==search: found=1
但没有for
循环没有一个(更好的)方法吗? 我不需要知道i
或在发现后继续循环。
你总是会有一个循环 – 有人可能会来一个聪明的一行,隐藏在一个调用map()
或类似的循环,但它总是会在那里。
我的select总是要有干净和简单的代码,除非性能是一个主要因素。
这可能是你的代码更Pythonic版本:
data = [['a','b'], ['a','c'], ['b','d']] search = 'c' for sublist in data: if sublist[1] == search: print "Found it!", sublist break # Prints: Found it! ['a', 'c']
只要发现匹配,它就会跳出循环。
(顺便说一句,你的错字是在['b''d']
。)
这是Pythonic的方式来做到这一点:
data = [['a','b'], ['a','c'], ['b','d']] search = 'c' any(e[1] == search for e in data)
或者…呃,我不打算宣称这是“一种真正的Pythonic方法”来做到这一点,因为在某种程度上它变成了一个主观的什么是Pythonic,什么不是,或哪种方法比Pythonic更另一个。 但是使用any()
肯定比for
循环更典型的Python风格,比如RichieHindle的回答 ,
当然,在执行any
有一个隐藏的循环,尽pipe一旦find匹配就会跳出循环。
自从我感到无聊以来,我制定了一个计时脚本来比较不同build议的性能,根据需要修改其中的一些,以使API相同。 现在,我们应该记住,最快并不总是最好的,速度与Pythonic绝对不是一回事。 这就是说,结果是…奇怪。 显然for
循环速度非常快,这不是我所期待的,所以我会毫不理解为什么他们会这样做。
无论如何,当我用问题中定义的列表分别从最快到最慢的两个元素的三个子列表,我得到了这些结果:
- RichieHindle用
for
循环的答案是0.22μs - Terence Honles的第一个build议是在0.36μs创build一个清单
- Pierre-Luc Bedard的答案(最后一个代码块) ,时间为0.43μs
- 从原始问题到0.48μs, Markus的答案和
for
循环之间基本上是一致的 - Coady的答案使用
operator.itemgetter()
,时间为0.53μs - 足够接近以计算作为亚历克斯·马尔泰利的回答与
ifilter()
和ifilter()
农的答案之间的联系 ,在0.67微秒(亚历克斯的一贯约半微秒快) - 另一个与jojo的答案 ,我的, 布兰登E泰勒 (这是我的相同),和特伦斯·Honles的第二个build议使用
any()
,都在0.81-0.82微秒 - 然后user27221的答案使用嵌套的列表parsing,0.95μs
显然,实际的时间对其他人的硬件没有意义,但是它们之间的差异应该给出一些关于不同方法有多接近的想法。
当我使用更长的列表时,情况会有所改变。 我从这个问题的名单开始,有三个子列表,并附加了197个子列表,每个子列表总共有200个子列表。 使用这个更长的列表,这里是结果:
- RichieHindle的答案与较短的列表相同,为0.22μs
- Coady的回答使用
operator.itemgetter()
,同样在0.53μs - Terence Honles的第一个build议是在0.36μs创build一个清单
- Alex Martelli的回答与
ifilter()
和Anon的答案之间的另一个虚拟联系是在ifilter()
- 再次,我的回答, 布兰登E泰勒的相同的方法,和特伦斯Honles的第二个build议使用
any()
,都在0.81-0.82微秒
那些在列表延长的时候保持原来的时间。 其余的,没有,是
- 来自原始问题的
for
循环,时间为1.24μs - Terence Honles的第一个build议是在7.49μs创build一个清单
- Pierre-Luc Bedard的答案(最后一个代码块) ,时间为8.12μs
- 马库斯的答案是10.27微秒
- jojo的答案 ,在19.87μs
- 最后, user27221的答案使用嵌套列表parsing ,在60.59μs
>>> the_list =[ ['a','b'], ['a','c'], ['b''d'] ] >>> any('c' == x[1] for x in the_list) True
以上都看起来不错
但是你想保留结果吗?
如果是这样…
你可以使用以下
result = [element for element in data if element[1] == search]
那么简单一点
len(result)
让你知道是否有任何东西被发现(现在你可以做的东西与结果)
当然这不能处理长度小于1的元素(除非你知道它们总是大于长度1,那么你应该检查,在这种情况下,你应该使用一个元组吗?)(元组是不可变的)
如果你知道所有的项目都是一个设定的长度,你也可以这样做:
any(second == search for _, second in data)
或者为len(data [0])== 4:
any(second == search for _, second, _, _ in data)
…我会推荐使用
for element in data: ...
代替
for i in range(len(data)): ...
(为了将来的使用, 除非你想保存或使用'i' ,并且只是为了让你知道'0'不是必需的,如果你以非零值开始,你只需要使用完整的语法)
>>> my_list =[ ['a', 'b'], ['a', 'c'], ['b', 'd'] ] >>> 'd' in (x[1] for x in my_list) True
编辑添加:
由于我们使用了生成器expression式,所以David在使用任何和我使用的答案时都会结束匹配。 这是一个testing使用无限生成器来显示:
def mygen(): ''' Infinite generator ''' while True: yield 'xxx' # Just to include a non-match in the generator yield 'd' print 'd' in (x for x in mygen()) # True print any('d' == x for x in mygen()) # True # print 'q' in (x for x in mygen()) # Never ends if uncommented # print any('q' == x for x in mygen()) # Never ends if uncommented
我只是简单地使用而不是==和任何 。
Markus有一个避免使用这个词for
– 这里是另一个方法,对于长时间的the_list
s …应该有更好的性能:
import itertools found = any(itertools.ifilter(lambda x:x[1]=='b', the_list)
关于什么:
list =[ ['a','b'], ['a','c'], ['b','d'] ] search = 'b' filter(lambda x:x[1]==search,list)
这将返回列表中的每个列表,第二个元素等于search。
使用gen exp没有错,但如果目标是内联循环…
>>> import itertools, operator >>> 'b' in itertools.imap(operator.itemgetter(1), the_list) True
应该是最快的。
K旧post,但没有人使用列表expression来回答:P
list =[ ['a','b'], ['a','c'], ['b','d'] ] Search = 'c' # return if it find in either item 0 or item 1 print [x for x,y in list if x == Search or y == Search] # return if it find in item 1 print [x for x,y in list if y == Search]
>>> the_list =[ ['a','b'], ['a','c'], ['b','d'] ] >>> "b" in zip(*the_list)[1] True
zip()
通过索引将一堆列表和元素组合在一起,从而有效地移动列表列表matrix。 星号把the_list
的内容作为参数发送给zip
,所以你有效地传递了三个分开的列表,这正是zip
。 剩下的就是检查"b"
(或其他)是否在由你感兴趣的索引元素构成的列表中。
我认为使用嵌套列表parsing是解决这个问题的最优雅的方法,因为中间结果是元素所在的位置。 一个实现将是:
list =[ ['a','b'], ['a','c'], ['b','d'] ] search = 'c' any([ (list.index(x),x.index(y)) for x in list for y in x if y == search ] )
下面给出的是一个简单的方法来确切地在列表中的项目是在哪里。
for i in range (0,len(a)): sublist=a[i] for i in range(0,len(sublist)): if search==sublist[i]: print "found in sublist "+ "a"+str(i)