如何比较列表中的值而不使用python中的循环?

时间:2016-08-10 20:50:02

标签: python performance numpy vectorization

我有一个带有排序号码的列表l,例如

SELECT Description, Color
FROM TableA ta
INNER JOIN TableB tb ON ta.Description LIKE '%' + tb.Color

我试图查找给定数字是否在列表中的两个数字之间。

例如,如果给出了数字12,那么我想获得9和14,因为它们之间有12个。

我用for循环写了这个,

[1, 5, 6, 9, 14, 19]

但是,如果此循环位于另一个循环内并且具有非常大的列表,则这可能很慢。有没有办法在不使用循环的情况下执行此操作?例如,使用numpy因为我知道它对数组的处理能力很强。

2 个答案:

答案 0 :(得分:4)

您可以使用np.searchsorted -

idx = np.searchsorted(l,n)
out = np.take(l,[idx-1,idx])

答案 1 :(得分:2)

您可以使用bisect本机python模块。

它使用二分法算法在列表中查找插入索引,因此它非常快(log(n)而不是n)。此外,在流行的平台(Linux,Windows,...)上,它有一个本机实现:无与伦比。

然后报告此索引和下一个索引的值,以说明它们之间的数字。

具有各种输入和输出范围值的小示例。我使用这样的方法来解决背包问题并且非常有效。

# use bisect because the list is known to be sorted
from bisect import bisect

def test(value, l):
    idx = bisect(l, value)    
    # if idx is inside the list, we have a definite find
    if 0 < idx < len(l):
        return (l[idx-1], l[idx])
    # check for boundary condition error
    elif len(l) == idx and value == l[-1]:
        return (l[-2], l[-1])
    else:
        return None

def print_formatted_result(value, result):
    if result is None:      
        print (str(value) + " was not found")
    else:
        print (str(value) + " between " + str(result[0])+ " and " + str(result[1]))

z = [1, 5, 6, 9, 14, 19]
for searched in [0, 1, 9, 12, 19, 50]:
    result = test(searched, z)
    print_formatted_result(searched, result)

输出:

0 was not found
1 between 1 and 5
9 between 9 and 14
12 between 9 and 14
19 between 14 and 19
50 was not found

请注意,原始代码未找到19,但此代码将其作为特例报告。所有其他情况与原始代码匹配。