1

我有一个约 1GB 的数据条目文本文件和另一个我想用来过滤它们的名称列表。遍历每个条目的每个名称将非常缓慢。在 python 中执行此操作的最有效方法是什么?如果名称嵌入在条目中,是否可以使用哈希表?我可以使用名称部分一致放置的事实吗?

示例文件:

条目文件 - 条目的每个部分都由制表符分隔,直到名称

246   lalala   name="Jack";surname="Smith"
1357   dedada   name="Mary";surname="White"
123456  lala   name="Dan";surname="Brown"
555555   lalala   name="Jack";surname="Joe"

名称文件 - 每个都在换行符上

Jack
Dan
Ryan

期望的输出——仅在名称文件中有名称的条目

246   lalala   name="Jack";surname="Smith"
123456  lala   name="Dan";surname="Brown"
555555   lalala   name="Jack";surname="Joe"
4

4 回答 4

6

您可以使用set数据结构来存储名称——它提供了高效的查找,但如果名称列表非常大,那么您可能会遇到内存问题。

总体思路是遍历所有名称,将它们添加到 aset中,然后检查数据文件中每一行的每个名称是否包含在set. 由于条目的格式没有变化,您应该能够使用简单的正则表达式提取名称。

如果您遇到名称大小的问题set,您可以从名称文件中读取n行并为每组名称重复该过程,除非您需要排序。

于 2012-06-21T05:33:37.817 回答
2

我的第一个直觉是制作一个以名称为键的字典,假设使用字典中键的哈希查找名称是最有效的。

给定答案,@rfw 使用 a of names,我编辑了如下代码,并使用 a of names 和 aset对这两种方法进行了测试。dictset

我构建了一个包含超过 40 M 条记录和超过 5400 个名称的虚拟数据集。使用这个数据集,set 方法在我的机器上始终具有优势。

import re
from collections import Counter
import time

# names file downloaded from http://www.tucows.com/preview/520007
# the set contains over 5400 names
f = open('./names.txt', 'r')
names = [ name.rstrip() for name in f.read().split(',') ]
name_set = set(names) # set of unique names
names_dict = Counter(names) # Counter ~= dict of names with counts

# Expect: 246   lalala   name="Jack";surname="Smith"
pattern = re.compile(r'.*\sname="([^"]*)"')

def select_rows_set():
    f = open('./data.txt', 'r')
    out_f = open('./data_out_set.txt', 'a')
    for record in f.readlines():
        name = pattern.match(record).groups()[0]
        if name in name_set:
            out_f.write(record)
    out_f.close()
    f.close()

def select_rows_dict():
    f = open('./data.txt', 'r')
    out_f = open('./data_out_dict.txt', 'a')
    for record in f.readlines():
        name = pattern.match(record).groups()[0]
        if name in names_dict:
            out_f.write(record)
    out_f.close()
    f.close()

if __name__ == '__main__':
    # One round to time the use of name_set
    t0 = time.time()
    select_rows_set()
    t1 = time.time()
    time_for_set = t1-t0
    print 'Total set: ', time_for_set

    # One round to time the use of names_dict
    t0 = time.time()
    select_rows_dict()
    t1 = time.time()
    time_for_dict = t1-t0
    print 'Total dict: ', time_for_dict

我假设 a 本质Counter上是一个字典,并且更容易从数据集构建,不会增加访问时间的任何开销。如果我遗漏了什么,很高兴得到纠正。

于 2012-06-21T06:05:05.350 回答
1

您的数据被清晰地结构化为表格,因此这可能适用。 用于在内存中维护表格数据的数据结构?

于 2012-06-21T05:43:26.210 回答
1

您可以使用自己的“按名称搜索”功能创建自定义数据结构。那将是某种字典的列表。这应该比文本文件的大小占用更少的内存,因为它会删除每行上的重复信息,例如“姓名”和“姓氏”,这将是字典键。如果你知道一点 SQL(这里只需要很少的东西),那么使用 Python 过滤大文件,使用另一个文件的内容

于 2012-06-21T05:48:16.537 回答