【问题标题】:How do quickly search through a .csv file in Python如何在 Python 中快速搜索 .csv 文件
【发布时间】:2011-01-18 23:00:23
【问题描述】:

我正在使用 Python 读取一个包含 600 万个条目的 .csv 文件,并且我希望能够在该文件中搜索特定条目。

搜索整个文件有什么技巧吗?您应该将整个内容读入字典还是每次都执行搜索?我尝试将其加载到字典中,但这需要很长时间,所以我目前每次都在搜索整个文件,这似乎很浪费。

我可以利用该列表按字母顺序排列吗? (例如,如果搜索词以“b”开头,我只从包含以“b”开头的第一个词的行到包含以“b”开头的最后一个词的行)

我正在使用import csv

(附带问题:可以让csv 转到文件中的特定行吗?我想让程序从随机行开始)

编辑:我已经有一个列表的副本作为 .sql 文件,我该如何在 Python 中实现它?

【问题讨论】:

  • 我先将文件导入数据库。
  • 我忘了说我不是 Python 专家,因此非常感谢您提供代码示例。
  • 每次运行脚本会执行多少次查找?
  • 两个程序,一个是字典搜索,用户可以查询单词或变形词形,另一个是程序随机生成特定词形。查找次数基本上取决于用户想要查找的单词数。

标签: python dictionary csv large-files


【解决方案1】:

如果 csv 文件没有发生变化,请将其加载到数据库中,这样可以快速轻松地进行搜索。如果您不熟悉 SQL,则需要复习一下。

这是从 csv 插入 sqlite 表的粗略示例。示例 csv 是 ';'分隔,并且有 2 列。

import csv
import sqlite3

con = sqlite3.Connection('newdb.sqlite')
cur = con.cursor()
cur.execute('CREATE TABLE "stuff" ("one" varchar(12), "two" varchar(12));')

f = open('stuff.csv')
csv_reader = csv.reader(f, delimiter=';')

cur.executemany('INSERT INTO stuff VALUES (?, ?)', csv_reader)
cur.close()
con.commit()
con.close()
f.close()

【讨论】:

  • 我有点希望我不必使用 SQL 来执行此操作,Python 应该几乎和 Perl 处理字符串一样快? SQL真的更快吗? (我使用的是Linux,所以请尝试推荐跨平台软件)
  • @Baldur - 这不是 perl 与 python 的问题,你的问题是你重复读取一个大文件。 Perl 和 python 也会这样做。数据库只是为您提供更好的索引和搜索界面。
  • 我宁愿不使用数据库,因为我不熟悉 SQL,没有 SQL 就没有办法很好地实现这一点,如果没有,我应该使用什么数据库管理系统? mySQL 好用吗?在您的示例中,您不会将整个文件加载到数据库中,创建 600 万个元组吗?不是每次启动程序都占用很多时间吗?
  • @Baldur 这是一个非常简短而温馨的例子。您为什么不尝试一下,看看创建数据库需要多长时间并尝试几次搜索?谁知道呢,也许它是你的完美解决方案
  • @Baldur:我会像在我的示例中那样使用 sqlite。它快速、简单,并且数据库是单个文件。没有初始加载时间,因为数据结构在磁盘上,因此您无需等待将其加载到内存中。您可以通过为正在搜索的列创建和索引来加快速度。另外,了解一点 SQL 是一项很棒的技能。
【解决方案2】:

您可以对非常大的文件使用内存映射

import mmap,os,re
reportFile = open( "big_file" )
length = os.fstat( reportFile.fileno() ).st_size
try:
    mapping = mmap.mmap( reportFile.fileno(), length, mmap.MAP_PRIVATE, mmap.PROT_READ )
except AttributeError:
    mapping = mmap.mmap( reportFile.fileno(), 0, None, mmap.ACCESS_READ )
data = mapping.read(length)
pat =re.compile("b.+",re.M|re.DOTALL) # compile your pattern here.
print pat.findall(data)

【讨论】:

    【解决方案3】:

    好吧,如果你的单词不是太大(意味着它们会适合记忆),那么这里有一个简单的方法来做到这一点(我假设它们都是单词)。

    from bisect import bisect_left
    
    f = open('myfile.csv')
    
    words = []
    for line in f:
        words.extend(line.strip().split(','))
    
    wordtofind = 'bacon'
    ind = bisect_left(words,wordtofind)
    if words[ind] == wordtofind:
        print '%s was found!' % wordtofind
    

    加载文件中的所有值可能需要一分钟。这使用二进制搜索来查找您的单词。在这种情况下,我正在寻找培根(谁不会寻找培根?)。如果有重复的值,您可能还想使用 bisect_right 来查找 1 超出等于您正在搜索的值的最右边元素的索引。如果您有键:值对,您仍然可以使用它。您只需将单词列表中的每个对象都设为 [key, value] 列表。

    旁注

    我不认为你真的可以很容易地在 csv 文件中逐行查看。你看,这些文件基本上只是带有表示换行的 \n 字符的长字符串。

    【讨论】:

      【解决方案4】:

      您不能直接转到文件中的特定行,因为行是可变长度的,因此知道第 #n 行何时开始的唯一方法是搜索前 n 个换行符。仅仅查找 '\n' 字符是不够的,因为 CSV 允许在表格单元格中使用换行符,所以无论如何您都必须解析文件。

      【讨论】:

        【解决方案5】:

        我的想法是使用 python zodb 模块来存储字典类型的数据,然后使用该数据结构创建新的 csv 文件。在那个时候做你所有的操作。

        【讨论】:

          【解决方案6】:

          有一种相当简单的方法可以做到这一点。根据您希望 python 打印多少列,您可能需要添加或删除一些打印行。

          import csv
          search=input('Enter string to search: ')
          stock=open ('FileName.csv', 'wb')
          reader=csv.reader(FileName)
          for row in reader:
              for field in row:
                  if field==code:
                      print('Record found! \n')
                      print(row[0])
                      print(row[1])
                      print(row[2])
          

          我希望这能有所帮助。

          【讨论】:

          • 问题是快速搜索,而不是线性搜索!你回答了不符合快速条件的蛮力!
          猜你喜欢
          • 2012-03-17
          • 1970-01-01
          • 2020-12-11
          • 2014-10-14
          • 2014-11-27
          • 2012-05-25
          • 2011-07-30
          • 1970-01-01
          • 2021-10-01
          相关资源
          最近更新 更多