【问题标题】:Fast extraction of information from large text files with python使用python从大型文本文件中快速提取信息
【发布时间】:2017-09-10 05:45:08
【问题描述】:

我正在尝试编写一个可以在文档中搜索特定键的脚本。有时文档可能非常大,因为我想要一些可以真正快速高效并且使用尽可能少的内存的东西。

这是我的代码

Keys=('key1','key2','key3','key4','key5',...,'keyN')
LKeys=list(Keys)

with open('test.txt', 'r') as inF:
   for (N,line) in enumerate(inF):
      if any(x in line for x in LKeys):
           for k in LKeys:
               if k in line:
                  print N,k,line
                  print inF.next().strip() 
                  # Depending of the key sometimes I need to print next N lines
                  #Or do something else with the line for example save the next element after the key in a dictionary or database 
                  LKeyword.remove(k)
inF.close()

test.txt 可能看起来像这样。

sdjskjd key1 jdjdjjd : 4
sdjskjd key2 jdjdjjd: 3 hdhdhd:NaN 

sdjskjd key4 jdjdjjd:
dfdgdfdfdffddfdf2t3h
dfdfdfdfdf5dfd3fhth21
dfdfdfdgghhgdhhghjh
.
.
.
sdjskjd keyN jdjdjjd : 1213.5678 Inz:Joe 

例如:

Author  Antoine de Saint-Exupéry
Original title  Le Petit Prince
Translator  (English editions)
Katherine Woods
T.V.F. Cuffe
Irene Testot-Ferry
Alan Wakeman
Richard Howard[1]
David Wilkinson
Illustrator Antoine de Saint-Exupéry
Cover artist    Antoine de Saint-Exupéry
Country France
Language    French
Publisher   Reynal & Hitchcock (U.S.)
Gallimard (France)[2]
Publication date
September 1943 (U.S.: English & French)
(France, French, 1945)[2][Note 1]
Preceded by Pilote de guerre (1942)
Followed by Lettre à un otage (1944)

Author  Jostein Gaarder
Original title  Sofies verden
Country Norway
Language    Norwegian
Genre   Philosophical novel
Publisher   Berkley Books, Farrar, Straus and Giroux (original hardcover), MacMillan (audio)
Publication date
1991
Published in English
1994
Media type  Print (hardcover & paperback) and audiobook (English, unabridged CD & download)
Pages   518 pp
ISBN    978-1-85799-291-5
ISBN 978-1-4272-0087-7
ISBN 978-1-4272-0086-0
OCLC    246845141
LC Class    MLCM 92/06829 (P)

Auteur  Gabriel García Márquez
Pays    Drapeau de la Colombie Colombie
Genre   Roman
Réalisme magique
Version originale
Langue  Espagnol
Titre   Cien años de soledad
Éditeur Editorial Sudamericana
Lieu de parution    Buenos Aires
Date de parution    1967
Version française
Traducteur  Claude et Carmen Durand
Éditeur Éditions du Seuil
Lieu de parution    Paris
Date de parution    1968
Couverture  Élizabeth Butterworth
Nombre de pages 437
ISBN    202023811X

我读到,有时按顺序访问行的简单迭代是搜索和匹配大型文档的内存需求较少的方式,有时可能比正则表达式更快。

一些关于我的密钥的 cmets 通常按顺序出现在我的文档中,如果找到该密钥,它将不会再次出现,因为我将其从列表中删除,但是,在某些情况下并非所有密钥都出现在文档中,但如果找到 key2 然后 key4 很可能 key3 不在文档中。此外,键是不可变的,并且在文档中显示为准确的单词。

有没有更好、更高效、更简洁的代码结构方式?

【问题讨论】:

  • 如果与 open 一起使用,则不需要关闭 InF ...

标签: python performance memory-management text-files


【解决方案1】:

所以下面的代码不是使用元组或列表作为键,而是使用集合。所以这意味着如果有数千个键,查找仍然是恒定的时间。而在列表中,如果您这样做key in ['key', ..., 'keyN']

,则必须遍历列表

对于每一行,我们用空格分隔单词,以便我们可以在键中进行查找。然后如果这个词存在,我们就可以打印它。如果您需要从键中删除键,则必须缩小拆分词并再次检查。

但是,由于对集合中密钥的检查是在恒定时间内发生的,因此出于效率原因,您实际上不必删除密钥。

考虑到一行中只能有这么多单词,这样会更有效。但是可能有 N 个键。

keys = {'key1','key2','key3','key4','key5',...,'keyN'}

with open('test.txt', 'r') as f:
    for no, line in enumerate(f):
        words = line.split()
        for word in words:
            if word in keys:
                print(no, line)
                # find out which word actually matched by repeatedly 
                # shrinking a copy of the list words. 
                # then you could remove the key from keys

另外,您不需要关闭文件。上下文管理器(即 with)负责在文件被读取后关闭文件。

【讨论】:

  • 如果一个关键字重复多个但我只需要第一个匹配的数据怎么办?例如,如果键是keys={'Author','Language','Version'},我只需要第一本书的信息。
  • 恐怕我听不懂。在你的问题中举一个更好的例子?
【解决方案2】:

在文本文件中搜索关键字

我对您的代码做了一些调整。我不知道这是否是您要找的东西,但这无论如何都有效。

Keys = ('Cover', "Cuffe")


with open('test.txt', 'r', encoding="utf-8") as inF:
    for (N, line) in enumerate(inF):
        if any(x in line.split() for x in Keys):
            for k in Keys:
                if k in line.split():
                    print("(line)", N,
                          "(key)", k,
                          "(result)", line)

输出(使用您的 txt 文件示例中的数据)是:

(line) 4 (key) Cuffe (result) T.V.F.袖口

(line) 10 (key) Cover (result) 封面艺术家 Antoine de 圣埃克苏佩里

python 2.7 版本

Keys = ('Cover', "Cuffe")

with open('test.txt', 'r', encoding="utf-8") as inF:
    for (N, line) in enumerate(inF):
        if any(x in line.split() for x in Keys):
            for k in Keys:
                if k in line.split():
                    print "(line)", N,
                          "(key)", k,
                          "(result)", line

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-31
    • 1970-01-01
    • 1970-01-01
    • 2022-06-30
    • 1970-01-01
    • 2022-12-04
    相关资源
    最近更新 更多