快速查找值低于或等于的第一个条目

时间:2015-07-14 22:08:44

标签: python

我们在Python中说我有一个各自大小的文件列表,表示为dict(我不关心结构,你可以提出另一个):

from random import randint

def gen_rand_fileslist(nbfiles=100, maxvalue=100):
    fileslist = {}
    for i in xrange(nbfiles):
        fileslist["file_"+str(i)] = randint(1, maxvalue)
    return fileslist

fileslist = gen_rand_fileslist(10)

示例fileslist

{'file_0': 2,
 'file_1': 21,
 'file_2': 20,
 'file_3': 16,
 'file_4': 12,
 'file_5': 67,
 'file_6': 95,
 'file_7': 16,
 'file_8': 2,
 'file_9': 5}

现在我想快速找到低于指定阈值的最高值。例如:

get_value_below(fileslist, threshold=25) # result should be 'file_1' with value 21

函数get_value_below()将在紧密循环中调用,因此它应该尽可能快,并且可以指定任何阈值(因此排序不会直接帮助)。

有没有办法比仅仅遍历整个列表(线性时间)更快?

2 个答案:

答案 0 :(得分:3)

这完全取决于您在fileslist中搜索阈值的频率。如果您要执行的不仅仅是Θ(log n)次查询,那么最好先排序,然后对每个查询执行二进制搜索。否则,如果你只想执行一个查询,那么是线性搜索更好,因为你想要的元素几乎可以在任何地方,你肯定需要访问列表中的每个元素。

如果您计划先使用排序,然后使用二进制搜索,那么使用bisect_right作为输入x,它将返回列表中包含最大元素低于或等于的位置到x

答案 1 :(得分:1)

我建议使用pandas DataFrame,它可以快速解决您的搜索问题。

考虑以下示例:

         0
21  file_1

<强> OUT:

np.nonzero(sorted<=x)[0]

不要线性搜索已排序的数组,使用二进制搜索(duh)。一方面,这是CS 101孩子的东西。另一方面,我不知道bisect库,并且代码中充满了(function() { 'use strict'; angular .module('antApp') .controller('StartMenuController', StartMenuController); function StartMenuController($scope, $rootScope, $state){ var self = $scope; self.app = $rootScope; self.init = init; self.startGame = startGame; init(); function init(){ }; function startGame (){ $state.go('main'); }; }; 。一旦我切换到使用bisect_left / bisect_right,我看到了巨大的性能提升。编辑:在评论中,Peter指出NumPy实现了一个更快的二进制搜索,名为searchsorted;你(和我)可能应该使用它!。

来自http://docs.pylonsproject.org/projects/colander/en/latest/binding.html#what-is-schema-binding的一些有用的引用:

  韦斯麦金尼是个天才。如果你正在实施Wes McKinney已经放入他的图书馆熊猫的任何东西,那就停下来吧。他的代码比你要编写的任何内容更快,更强大,更可能更正确。想滚动窗口聚合器?使用熊猫。

     

需要处理丢失的数据吗?使用熊猫。你是在编写某种令人难以置信的丑陋黑客,试图在NumPy阵列上实现连接和分组,但实际上却花了3个小时来计算一个微妙的错误结果? (我已经这样做了)。耶稣基督,停止并使用大熊猫。