Python 可以使用Dict而不是list应用二分法吗?

Python 可以使用Dict而不是list应用二分法吗?,python,Python,我有一个文件,其中包含以下格式的信息: .343423 1 .434322 1 .453434 1 .534342 1 按排序顺序使每行和每行大小相等..我有一个带值的变量“a”,需要得到与第一列中的值相比最接近“a”的行号 到目前为止,我一直在将第一列元素处理到列表中,然后使用对分方法得到行数…但由于我需要多次执行此操作…这变得非常缓慢,因为我每次都需要将大约4000个元素复制到列表中 所以现在我想用dict来代替数据结构,因为我会更快…但是我不知道我们是否可以在对分中使用dict,如果可能

我有一个文件,其中包含以下格式的信息:

.343423 1
.434322 1
.453434 1
.534342 1
按排序顺序使每行和每行大小相等..我有一个带值的变量“a”,需要得到与第一列中的值相比最接近“a”的行号

到目前为止,我一直在将第一列元素处理到列表中,然后使用对分方法得到行数…但由于我需要多次执行此操作…这变得非常缓慢,因为我每次都需要将大约4000个元素复制到列表中

所以现在我想用dict来代替数据结构,因为我会更快…但是我不知道我们是否可以在对分中使用dict,如果可能的话,我们如何在这种情况下使用请建议。。。 如果不可能,他们是否有比正常更快地将数据加载到列表中的方法???
谢谢你…

我不明白你为什么要复制这些元素。这是慢的部分。您不能在启动时加载一次列表,然后始终使用相同的列表吗


无论如何,dict比list慢(我相信[不确定]它是作为哈希映射实现的,因此没有顺序,因此不能使用对分)。

dict是无序的,所以对其使用对分是没有意义的

我可以想出几个选择:

1) 将数据保存在(键、值)元组的排序列表中。这将允许您使用对分查找最近的元素。如果这是您唯一想对列表执行的操作,并且列表不会随时间发生太大变化(因为每次都需要使用它,这会产生成本),那么这是很好的


2) 使用平衡的二叉树数据结构-有几种。这将为您提供类似字典的语义,同时能够像bisect一样找到最近的元素。PyPi搜索中的第一项是,看起来它可以做任何你想做的事情。它的作用类似于一个字典,但有额外的方法来获取给定值前后的项。这将让您高效地找到最接近的数字

如果您在中读取整个文件,则字典将比列表快,因为必须搜索列表(O(lg n)),而字典提供快速查找,而不管大小(O(1))。当然,您不会在字典上使用二分法(二进制搜索)。如果您只在任何特定文件中查找一行,您甚至不需要这样做——您只需读取该文件,直到找到要查找的行


如果每个文件的查找次数很少,则可以通过直接对文件本身进行二进制搜索来加快查找速度。由于您知道文件已排序,并且每条记录的长度相同,因此您可以轻松编写代码,以便只读取搜索所需的文件字节。

以下是一种使用对分的方法,而无需读取整个文件。不管怎样,操作系统最终读取的文件都会比您需要的多得多,因此在
data.txt
足够大之前,您不会看到性能提升

from os import SEEK_END
from bisect import bisect

class ListProxy(object):
    def __init__(self, f):
        self.f = f
        self.line_len = len(f.readline())
        self.f.seek(0, SEEK_END)
        self.num_lines = self.f.tell()//self.line_len

    def __len__(self):
        return self.num_lines

    def __getitem__(self, idx):
        self.f.seek(idx*self.line_len)
        return float(self.f.read(7))

with open("data.txt") as f:
    lp = ListProxy(f)    
    num = .44
    idx = bisect(lp, num)
    if idx != 0 and num - lp[idx-1] < lp[idx] - num:
        idx -=1
    print num, idx
从操作系统导入搜索\u结束
从对分导入对分
类ListProxy(对象):
定义初始化(self,f):
self.f=f
self.line_len=len(f.readline())
self.f.seek(0,seek\u结束)
self.num\u lines=self.f.tell()//self.line\u len
定义(自我):
返回self.num\u行
def uu getitem uu(self,idx):
self.f.seek(idx*self.line_len)
回油浮子(自f读数(7))
将open(“data.txt”)作为f:
lp=ListProxy(f)
num=.44
idx=二等分(lp,num)
如果idx!=0和num-lp[idx-1] > p>类似于Dave Kirby的解,考虑模块on。它是纯Python,并提供了一个覆盖键的方法。对于从文件批量加载数据,它也比平衡二叉树类型快得多

在您的情况下,类似的方法可能会起作用:

from sortedcontainers import SortedDict
with open('data.txt') as fptr:
    sd = SortedDict(map(int, line[1:].split()) for line in fptr)

# sd now contains key, value pairs corresponding to the columns in your data file
# Lookup index of desired key:

pos = sd.bisect(434323)

# pos points to the index of the key 434322
# get that key:

key = sd.iloc[pos]

# now get the value:

value = sd[key]

在sortedcontainers模块中,二分法、索引和键查找操作都非常快速。此解决方案要求您可以将文件的全部内容保留在内存中。

我每次打开的文件都不同,因此列表也会不同。因此,任何建议都没有机会改进!这里最大的问题是磁盘访问速度比其他任何东西都慢。一次加载所有数据,考虑将它们放入sqlite数据库,但不要每次都访问文件,并期望它会很快。我恳请您提供一些示例代码…如果不是完整的代码..我无法清楚地理解您的意思,但您的建议看起来更快..因此,您可以指导我如何编写代码…Thnqd您是否可以控制文件格式?也许你可以用二进制格式代替这个问题的背景,复习所有的OP问题。