【问题标题】:How can I make this search faster in python?如何在 python 中使这个搜索更快?
【发布时间】:2013-06-04 20:47:31
【问题描述】:

我正在从另一个文件的行中搜索一个值。确切的值只会在搜索文件中出现一次。我怎样才能使这个过程更快?这是我当前的代码:

filltaxlist = open("file with query number.txt", "rw")
fulltaxa = open("output file with hit line match", "rw")

for line in filltaxalist:
    line = line.strip()
    taxid = re.split("\t", line)
    lookup = taxid[5] # this value is a number and I need the exact match only so I convert it to an integer
    int1 = int(lookup)
    for line in open("File to search.txt", "r"):
        data = re.split(',', line)
        hit = int(data[0]) # every value in this file is a number separated by a ,
        if lookup in line:
            if int1 == hit:
                fulltaxa.write(line)

这很好用,因为它写得很慢。此外,我正在搜索的文件大小超过 GB。

filltaxlist 行示例:

cvvel_1234    403454663    29.43    3e-30    55.55555555234    1172189
cvell_1444    2342333      30.00    1e-50    34.34584359345    5911
cvell_1444    234230055    23.23    1e-60    32.23445983454    46245
cvell_1444    233493003    23.44    1e-43    35.23595604593    46245

fulltaxa 应该返回什么:

1172189, 5943, 1002030, 12345
5911, 11234, 112356, 234, 3456, 44568, 78356
46245, 123, 3432456, 123488976, 23564, 334
46245, 123, 3432456, 123488976, 23564, 334

【问题讨论】:

  • filltaxalist 中的每一行都通读一次文件。
  • if int == hit 我想应该是if int1 == hit
  • filltaxlist 很大吗?
  • filltaxlist 将是 ~10-30 千行
  • 您基本上是在尝试在没有真实数据库的情况下进行表连接。如果您有足够的内存将来自filltaxlist 的数据放入一个列表(或者更好的是,以taxid 为键的某种字典),那么就这样做。否则,您可能会调查将所有这些信息放入真正的数据库中。

标签: python performance search int


【解决方案1】:

使用数据库

正如其他人所提到的,最简单的方法可能是将其转储到数据库中(例如 sqllite)。如果需要与语言交互,可以使用 python 绑定。

纯 Python 解决方案

对于filltaxlist 中的每个条目,您完全读取fulltaxa(由于嵌套的顺序),首先缓存所有查询,然后只读取一次fulltaxa,然后对输出进行排序会更有效重新获得fulltaxa 的订单。

由于查询的顺序是导入的,我们应该使用 FIFO 结构 - deque 在我们的例子中会很好。

from collections import defaultdict
filltaxlist = open("file with query number.txt", "rw")
fulltaxa = open("output file with hit line match", "rw")

possibles = {}
for i, line in enumerate(filltaxalist):
    line = line.strip()
    taxid = re.split("\t", line)
    lookup = taxid[5] # this value is a number and I need the exact match only so I covert it to an integer
    int1 = int(lookup)
    possibles[int1] = i

output_lines = defaultdict(list)
for line in open("File to search.txt", "r"):
    data = re.split(',', line)
    hit = int(data[0]) # every value in this file is a number separated by a ,
    if hit in possibles:
        output_lines[possibles[hit]].append(line)

fulltaxa.writelines(line for lines in output_lines.values() for line in lines)

当你用完查询时,上面的代码会抛出一个 IndexError

其他一些小的改进。

data = re.split(',', line)

可能比

data = line.split(',')

但是您应该配置文件以确保这在您的情况下是有意义的。

【讨论】:

  • 谢谢你。集合只会收集唯一值吗?我最初将其读入列表,但仍必须搜索 filltaxalist 中的重复值。
  • set 只会收集唯一值,如果您需要知道每个值的实例数(例如,如果您想搜索前 3 个实例),请将其切换为 counter查询列表中有 3 个重复项)。
  • 为了让这个过程正常工作,发生顺序、天气重复或唯一值非常重要,这就是我逐行进行的原因。 filltaxlist 中的第 1 行必须与 fulltaxa 中的第 1 行匹配。为了清楚起见,我将在问题中添加每个文件的示例。
  • 正确,这就是我对这个答案有疑问的原因。 “file to search.txt”的顺序是 data[0] 上的数字。
  • 它只是按照filltaxlist中的查询顺序想要的输出?
【解决方案2】:

你的算法是 O(m * n)。可以通过使用字典来制作 O(m + n) 算法。即使 m 很小,它也可能是 Python 中的一个重大改进,其中字典访问的常量因素与任何其他语句没有太大区别。

filltaxalist = open("file with query number.txt", "rw")
fulltaxa = open("output file with hit line match", "rw")

filltaxadict = {}
for i, line in enumerate(filltaxalist):
    line = line.strip()
    taxid = re.split("\t", line)
    lookup = taxid[5] # this value is a number and I need the exact match only so I convert it to an integer
    int1 = int(lookup)

    filltaxadict[int1] = i

results = [[]] * len(filltaxadict)
for line in open("File to search.txt", "r"):
    data = re.split(',', line)
    hit = int(data[0]) # every value in this file is a number separated by a ,
    match = filltaxadict.get(hit)
    if match is not None:
        results[match].append(line)

for result in results:
    fulltaxa.writelines(result)

这会以正确的顺序处理重复项;如果你不需要,稍微简单一点。要搜索的文件可能很大;这不会将其内容保留在内存中,只会保留 filltaxalist 的(部分)内容,我认为它不会异常大。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-11-03
    • 1970-01-01
    • 2014-11-14
    • 1970-01-01
    • 1970-01-01
    • 2011-01-18
    • 2020-08-06
    相关资源
    最近更新 更多