4

我想从包含“b”作为第一个元素的子列表中检索整数值(b 只会在列表中出现一次)

我想到了这两种方法:

foo = [["a", 5], ["b", 10], ["c", 100]]

y = filter(lambda x: x[0] == "b", foo)
print y[0][1]

z = [foo[i][1] for i in range(len(foo)) if foo[i][0] == "b"] 
print z[0]

他们都工作。两者中的任何一个都更可取(关于运行时间),还有更好的第三种方法吗?

4

2 回答 2

11

当列表很小时,两者之间没有显着差异。如果输入列表可以变大,那么就会出现更严重的问题:您正在遍历整个列表,而您可能会在第一个元素处停止。您可以使用 for 循环来完成此操作,但如果您想使用类似理解的语句,请使用生成器表达式

# like list comprehensions but with () instead of []
gen = (b for a, b in foo if a == 'b')
my_element = next(gen)

或者简单地说:

my_element = next(b for a, b in foo if a == 'b')

如果您想了解有关生成器表达式的更多信息,请查看PEP 289


请注意,即使使用生成器和迭代器,您也有不止一种选择。

# Python 3:
my_element = next(filter(lambda x: x[0] == 'b', foo))

# Python 2:
from itertools import ifilter
my_element = next(ifilter(lambda (x, y): x == 'b', foo))

我个人不喜欢也不推荐这个,因为它的可读性要差得多。事实证明,这实际上比我的第一个片段要慢,但filter()在某些特殊情况下,通常使用而不是生成器表达式可能会更快。

无论如何,如果您需要对代码进行基准测试,我建议您使用timeitmodule

于 2013-03-13T11:38:48.037 回答
4

这比 DavidE 的回答慢(我计时了),但具有简单的优点:

z = dict(foo)['b']

当然,它假设您的密钥都是可散列的,但如果它们是字符串,那就没问题了。如果您需要进行多次查找,尽管这绝对是要走的路(只要确保只转换为 dict 一次)。

于 2013-03-13T11:46:27.760 回答