我有一个包含以下模式信息的文件:
.343423 1
.434322 1
.453434 1
.534342 1
按排序顺序对每一行和每行的大小相等。我有一个带有值的变量“a”,需要得到与第一列中的值相比最接近“a”的行号。
直到现在我正在将第一列元素复制到列表中然后使用bisect方法我得到了row_num ...但是因为我需要执行这么多次...这已经变得非常缓慢,因为我需要复制一些4000每次列出的元素..
所以现在我想用dict而不是数据结构这样做,因为我会更快...但我不知道我们是否可以在bisect中使用dict如果可能我们如何使用这种情况请建议... 如果不可能,他们是否有任何方法将数据加载到列表中更快,然后正常??? 感谢你......
答案 0 :(得分:5)
与Dave Kirby的解决方案类似,请考虑sortedcontainers上的PyPI模块。它是纯Python,fast,并且在密钥上提供SortedDict type with bisect。它还比平衡二进制树类型更快地从文件批量加载数据。
在你的情况下,这样的事情可能有效:
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模块中都非常快。此解决方案要求您可以将文件的全部内容保留在内存中。
答案 1 :(得分:1)
Dicts是无序的,所以在它们上使用bisect是没有意义的。
我可以想到几个选项:
1)将数据保存在(键,值)元组的排序列表中。这将允许您使用bisect来查找最接近的元素。如果这是你唯一想要对列表做的事情,并且如果列表随着时间的推移没有太大变化(因为每次都需要使用它,这将有成本),这很好。
2)使用平衡二叉树数据结构 - 有几个Python implementations available on PyPi。这将为您提供类似字典的语义,同时能够找到像bisect这样的最接近的元素。 PyPi搜索中的第一项是bintrees,看起来它会做你想做的一切。它的作用类似于字典,但有其他方法可以获取给定值之前和之后的项目。这将让您有效地找到最接近的数字。
答案 2 :(得分:1)
这是一种在不读取整个文件的情况下使用bisect
的方法。操作系统最终会读取比你需要的更多的文件,所以在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
答案 3 :(得分:0)
我不明白为什么你需要复制元素。这是缓慢的部分。你不能在启动时加载列表一次,然后总是使用相同的列表吗?
dict总是比列表慢(我相信[不确定]它是作为hash_map实现的,因此没有顺序,因此你不能使用bisect)。
答案 4 :(得分:0)
如果您正在读取整个文件,则字典将比列表更快,因为必须搜索列表(O(lg n)),而字典提供快速查找而不管大小(O(1)) 。当然,你不会在字典上使用二分法(二分法搜索)。如果您只是在任何特定文件中查找单行,您甚至不需要这样做 - 您只需阅读该文件,直到找到您要查找的行。
如果每个文件的查找次数很少,您可以通过直接对文件本身进行二进制搜索来加快速度。由于您知道文件已排序且每条记录的长度相同,因此您可以轻松编写代码,以便只读取搜索所需文件的字节数。