【问题标题】:How to check if a word is in a string without using multiple loops如何在不使用多个循环的情况下检查单词是否在字符串中
【发布时间】:2021-07-29 10:29:07
【问题描述】:

所以这个程序的目的是为ner.txt中的每个单词找到例句。例如,如果单词applener.txt 中,那么我想查找是否有任何句子包含单词apple 并输出类似apple: you should buy an apple juice 的内容。

所以代码的逻辑非常简单,因为我在ner.txt. 中每个单词只需要一个例句。我正在使用 NLTK 来确定它是否是一个句子。

问题出在代码的底部。我正在使用 2 个 for 循环来查找每个单词的例句。这非常缓慢并且不适用于大文件。我怎样才能使这个高效?或者没有我的逻辑有没有更好的方法来做到这一点?

from nltk.tokenize import sent_tokenize

news_articles = "test.txt"
oov_ner = "ner.txt"

news_data = ""
with open(news_articles, "r") as inFile:
    news_data = inFile.read()

base_news = sent_tokenize(news_data)

with open(oov_ner, "r") as oovNER:
    oov_ner_content = oovNER.readlines()

oov_ner_data = [x.strip() for x in oov_ner_content]

my_dict = {}

for oovner in oov_ner_data:
    for news in base_news:
        if oovner in news:
            my_dict[oovner] = news
            print(my_dict)

【问题讨论】:

  • 嗨,你可以做的最好的方法是,首先标记你检测到的句子,然后创建倒排索引,然后每个单词就像一个查询一样在倒排索引中找到。其他方式你可以做到这一点,如果你不想使用倒排索引,你可以使用 itertool python 模块中的 Product() 方法在一个列表中创建所有句子和单词对,然后使用一个循环来比较它们。

标签: python python-3.x nlp nltk


【解决方案1】:

这是我要做的:将过程分为两个步骤,索引创建和查找。

from nltk.tokenize import sent_tokenize, word_tokenize

# 1. create a reusable word index like {'worda': [2, 4, 10], 'wordb': [1, 9]}
with open("test.txt", "r", encoding="utf8") as fp:
    news_sentences = sent_tokenize(fp.read())

index = {}
for i, sentence in enumerate(news_sentences):
    for word in word_tokenize(sentence):
        word = word.lower()
        if word not in index:
            index[word] = []
        index[word].append(i)

# 2. look up words from that index and retrieve the associated sentences
with open("ner.txt", "r", encoding="utf8") as fp:
    oov_ner_data = [l.strip() for l in fp.readlines()]

matches = {}

for word in oov_ner_data:
    word = word.lower()
    if word in index:
        matches[word] = [news_sentences[i] for i in index[word]]

print(matches)

无论在您的文本上运行 sent_tokenize()word_tokenize() 需要花费多少时间,第 1 步都需要很长时间。您对此无能为力。但是您只需要执行一次,然后就可以非常快速地针对它运行不同的单词列表。

同时运行sent_tokenize()word_tokenize() 的优点是它可以防止由于部分匹配而导致误报。例如,如果句子包含“embark”,您的解决方案会找到“bark”的正匹配,而我的不会。换句话说 - 产生错误结果的更快解决方案并不是一种改进。

【讨论】:

    【解决方案2】:

    我不会像现在这样使用一个单词,即外部 for 循环,而是交换循环并在找到与句子匹配的单词时中断 - 这样可以节省一些时间,因为现在,您正在使用“oovner”并尝试将其与“base_news”中的每个句子“news”进行匹配。如果你交换循环,一旦找到匹配项,你就可以退出。

    这个:

    for oovner in oov_ner_data:
        for news in base_news:
            if oovner in news:
                my_dict[oovner] = news
                print(my_dict)
    

    进入这个:

    for news in base_news:
        for oovner in oov_ner:data:
            if oovner in news:
                my_dict[oovner] = news
                print(my_dict)
                break 
    

    我不会称其为最佳,但它应该可以加快速度。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-04-30
      • 2011-10-31
      • 2021-04-18
      • 2017-06-15
      • 1970-01-01
      相关资源
      最近更新 更多