我有一个包含嵌套列表的列表,我需要知道在这些嵌套列表中搜索最有效的方法。
例如,如果我有:
[['a','b','c'],
['d','e','f']]
如果我必须在整个列表中查找'd',那么最有效的方法是什么?
我有一个包含嵌套列表的列表,我需要知道在这些嵌套列表中搜索最有效的方法。
例如,如果我有:
[['a','b','c'],
['d','e','f']]
如果我必须在整个列表中查找'd',那么最有效的方法是什么?
>>> lis=[['a','b','c'],['d','e','f']]
>>> any('d' in x for x in lis)
True
使用 any
的生成器表达式
$ python -m timeit -s "lis=[['a','b','c'],['d','e','f'],[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]" "any('d' in x for x in lis)"
1000000 loops, best of 3: 1.32 usec per loop
生成器表达式
$ python -m timeit -s "lis=[['a','b','c'],['d','e','f'],[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]" "'d' in (y for x in lis for y in x)"
100000 loops, best of 3: 1.56 usec per loop
列表推导式
$ python -m timeit -s "lis=[['a','b','c'],['d','e','f'],[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]" "'d' in [y for x in lis for y in x]"
100000 loops, best of 3: 3.23 usec per loop
如果项目接近末尾或根本不存在怎么办?any
比列表推导更快。
$ python -m timeit -s "lis=[['a','b','c'],['d','e','f'],[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]"
"'NOT THERE' in [y for x in lis for y in x]"
100000 loops, best of 3: 4.4 usec per loop
$ python -m timeit -s "lis=[['a','b','c'],['d','e','f'],[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]"
"any('NOT THERE' in x for x in lis)"
100000 loops, best of 3: 3.06 usec per loop
如果列表长度增加1000倍呢?any
仍然更快。
$ python -m timeit -s "lis=1000*[['a','b','c'],['d','e','f'],[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]"
"'NOT THERE' in [y for x in lis for y in x]"
100 loops, best of 3: 3.74 msec per loop
$ python -m timeit -s "lis=1000*[['a','b','c'],['d','e','f'],[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]"
"any('NOT THERE' in x for x in lis)"
100 loops, best of 3: 2.48 msec per loop
我们知道生成器需要花费一些时间来设置,因此LC获胜的最佳机会是一个非常短的列表。
$ python -m timeit -s "lis=[['a','b','c']]"
"any('c' in x for x in lis)"
1000000 loops, best of 3: 1.12 usec per loop
$ python -m timeit -s "lis=[['a','b','c']]"
"'c' in [y for x in lis for y in x]"
1000000 loops, best of 3: 0.611 usec per loop
而且any
也使用更少的内存
mylist = [['a','b','c'],['d','e','f']]
'd' in [j for i in mylist for j in i]
True
这也可以使用生成器实现(如@AshwiniChaudhary所示)。
根据下面的评论更新:
这是相同的列表推导式,但使用更具描述性的变量名称:
'd' in [elem for sublist in mylist for elem in sublist]
for sublist in mylist:
for elem in sublist
in
运算符测试'd'。使用生成器表达式,在此情况下整个列表不会被遍历,因为生成器将逐个生成结果:
>>> lis = [['a','b','c'],['d','e','f']]
>>> 'd' in (y for x in lis for y in x)
True
>>> gen = (y for x in lis for y in x)
>>> 'd' in gen
True
>>> list(gen)
['e', 'f']
~$ python -m timeit -s "lis=[['a','b','c'],['d','e','f'],[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]" "'d' in (y for x in lis for y in x)"
100000 loops, best of 3: 2.96 usec per loop
~$ python -m timeit -s "lis=[['a','b','c'],['d','e','f'],[1,2,3],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[16,17,18]]" "'d' in [y for x in lis for y in x]"
100000 loops, best of 3: 7.4 usec per loop
timeit
的结果表明您的解决方案更好。 - Ashwini Chaudhary如果你只想知道你的元素是否在列表中存在,那么你可以将列表转换为字符串并进行检查。你可以扩展这种方法到更多嵌套的列表中。例如:[[1],'a','b','d',['a','b',['c',1]]]。如果你不知道嵌套列表的级别,但想知道可搜索项是否存在,则此方法很有帮助。
search='d'
lis = [['a',['b'],'c'],[['d'],'e','f']]
print(search in str(lis))
a[i][j] <= a[i][j+1]
和 a[i][-1] <= a[i+1][0]
(一个数组的最后一个元素始终小于或等于下一个数组的第一个元素),那么您可以通过执行以下操作来消除大量比较:a = # your big array
previous = None
for subarray in a:
# In this case, since the subarrays are sorted, we know it's not in
# the current subarray, and must be in the previous one
if a[0] > theValue:
break
# Otherwise, we keep track of the last array we looked at
else:
previous = subarray
return (theValue in previous) if previous else False
只有在您拥有大量数组并且它们都具有大量元素的情况下,这种优化才是值得的。
bisect
模块。 - John La Rooy
'd'
(即相对靠近列表前面的东西)的内容。如果您查看我和@Ashwini在他的答案下进行的讨论,您会发现在列表中选择“目标”的选择会产生重大差异。在我们的试验中,如果目标位于中间或末尾,LC击败了生成器。如果目标靠近前面,生成器则“获胜”。我认为最终结果非常依赖于特定的数据集和所寻找的目标。 - Levonany
仍然比LC更快。 - John La Rooy