Подсчет вхождений списка строк в тексте - PullRequest
0 голосов
/ 10 апреля 2020

Я хочу считать количество элементов списка в тексте с Python. Я знаю, что могу использовать .count(), но я прочитал, что это может повлиять на производительность. Кроме того, элемент в списке может содержать более 1 слова.

my_list = ["largest", "biggest", "greatest", "the best"]

my_text = "i have the biggest house and the biggest car. My friend is the best. Best way win this is to make the largest house and largest treehouse and then you will be the greatest"

Я могу сделать это:

num = 0
for i in my_list:
   num += my_text.lower().count(i.lower())

print(num)

Этот способ работает, но что если в моем списке 500 элементов и моя строка 3000 слов, так что в этом случае у меня очень низкая производительность.

Есть ли способ сделать это, но с хорошей / быстрой производительностью?

1 Ответ

2 голосов
/ 10 апреля 2020

Поскольку my_list содержит строки с более чем одним словом, вам нужно найти n-grams из my_text, чтобы найти совпадения, так как разделение по пробелам не подойдет. Также обратите внимание, что ваш подход не рекомендуется, так как для каждой отдельной строки в my_list вы будете обходить всю строку my_text, используя count. Лучшим способом было бы заранее определить n-grams, который вы будете искать заранее.

Вот один из подходов, использующий nltk s ngram. Я добавил еще одну строку в my_list, чтобы лучше проиллюстрировать процесс:

from nltk import ngrams
from collections import Counter, defaultdict

my_list = ["largest", "biggest", "greatest", "the best", 'My friend is the best']
my_text = "i have the biggest house and the biggest car. My friend is the best. Best way win this is to make the largest house and largest treehouse and then you will be the greatest"

Первый шаг - определить словарь, содержащий различные длины n-грамм, которые мы будем искать:

d = defaultdict(list)
for i in my_list:
    k = i.split()
    d[len(k)].append(tuple(k))

print(d)
defaultdict(list,
            {1: [('largest',), ('biggest',), ('greatest',)],
             2: [('the', 'best')],
             5: [('My', 'friend', 'is', 'the', 'best')]})

Затем разбейте my_text на список, и для каждого ключа в d найдите соответствующий n-grams и построите Counter из результата. Затем для каждого значения в этом указанном c ключе в d обновите значения из Counter:

my_text_split = my_text.replace('.', '').split()
match_counts = dict()
for n,v in d.items():
    c = Counter(ngrams(my_text_split, n))
    for k in v:   
        if k in c:
            match_counts[k] = c[k] 

, что даст:

print(match_counts)

{('largest',): 2,
 ('biggest',): 2,
 ('greatest',): 1,
 ('the', 'best'): 1,
 ('My', 'friend', 'is', 'the', 'best'): 1}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...