Поиск слов из словаря в текстовом формате и возврат значений - PullRequest
0 голосов
/ 13 сентября 2018

Моя функция должна находить слова из словаря в тексте, а затем складывать значения вместе в "точках" переменной.

Но я что-то напутал. Мой процесс выглядит следующим образом:

  1. Словарь:

    words = {'very funny': 3,'funny': 2,'accidentally funny': 1}  
    
  2. Текстовый файл (называемый: sample.txt):

Монти Пайтон очень забавный. + 3
Некоторые дураки смешные. + 2
Политики иногда случайно смешны. + 1
Настоящие питоны совсем не смешные. + 2

* значения представляют балл, который я хотел получить для каждой строки

  1. Получение текста из файла .txt:

    with open('sample.txt', 'r') as text:
        data = text.read()
    
  2. Функция:

    def counter(data): #this should find keywords
        default_value = 0 #var for stuff not included in dict
        points = 0 
        for i in data:
            points += words.get(i, default_value)  #using get to avoid valueError
        print(points)
        return points  
    
    counter(data)
    
  3. Выход:

    0  
    
    Process finished with exit code 0
    

edit Я знал, что о чем-то забыл;] :

Проблемы

  1. Кажется, моя функция еще ничего не считает
  2. Я хочу оценивать эти ключевые фразы таким образом, чтобы одно слово "забавный" не было тройным, а вызывало бы только эффект 'funny': 2. Я не знаю, как к этому подойти.

Это мой первый вопрос по стеку, поэтому, если я что-то испортил, пожалуйста, дайте мне знать.

Ответы [ 4 ]

0 голосов
/ 15 сентября 2018

Я бы так и сделал.Я бы разбил этот текст на список слов, а затем перебрал его.Я соединяю каждое слово с предыдущим.затем посмотрите слово в словаре.Конечно, я не могу соединить первое слово с тем, что было до него.Таким образом, переменная first_iteration имеет значение true только для первой итерации и заменяется на false в конце первой итерации на false.Я надеюсь, что это решит вашу проблему.

def counter(data): #this should find keywords
    default_value = 0 #var for stuff not included in dict
    points = 0 
    first_iteration = True
    wordsList = data.split()
    for i in wordList:
        if (!first_iteration):
            theWord = i + " " + prev
        points += words.get(theWord, default_value)  #using get to avoid valueError
        prev = i
        first_iteration = False
    print(points)
    return points  

counter(data)
0 голосов
/ 13 сентября 2018

Я предлагаю вам изменить свою логику - переберите термины и посчитайте, сколько раз они появляются:

def counter(data): #this should find keywords
    points = 0 
    for word, value in words.items():
        points += value * data.count(word)
    print(points)
    return points  

Однако это означает, что некоторые термины могут быть оценены более одного раза - 'very funny' также содержит 'funny', поэтому он должен стоить 5 (3 из 'very funny' и 2 из 'funny')

Ваш текст содержит 4 funny, 1 very funny и 1 accidentally funny, поэтому результат равен 4 * 2 + 3 + 1 = 12

0 голосов
/ 13 сентября 2018

Проблема здесь в вашей структуре данных.В общем, словари хороши, если вы хотите найти их.Однако, это не то, что вы делаете здесь.Вместо этого я бы посоветовал список кортежей.Итак, ваш words будет выглядеть так:

words = [ ("very funny", 3), ("funny", 2), ("accidentally funny", 1) ]

Далее, когда вы запускаете цикл for, вы выполняете итерации по каждому символу в строке вместо каждого слова.Вместо этого вам следует перебрать значения в words и найти количество вхождений каждого слова:

import re

total = 0
for w in words:
    total += w[1] * sum(re.finditer(w[0], data))

Однако, как уже указывалось, при этом будут найдены дубликаты.Чтобы избежать этого, вы должны заказать words в том порядке, в котором вы хотите их найти, и удалить значения, которые вы найдете в data:

words = [ ("very funny", 3), ("accidentally funny", 1), ("funny", 2) ]

total = 0
for w in words:
    total += len(list(re.finditer(w[0], data))) * w[1]
    data = data.replace(w[0], '')

Однако это не очень эффективно.Если вы хотите, чтобы это работало быстрее, я бы использовал LL parser .По сути, вы бы разбили свои данные на пробелы и итерировали бы по ним, вытягивая следующие k символов, где k - это количество слов в самой длинной записи в words.Вы должны объединить эти k слова вместе, используя пробелы, и проверить, соответствуют ли они какой-либо записи в words.В этом случае вы хотели бы использовать словарь, кстати.Вы можете сделать это следующим образом:

splitData = data.split(' \r\n')
total = 0
for i in range(0, len(splitData)):

    # Longest entry in words has two words so we use i + 2
    phrase = ' '.join(splitData[i:(i + 2)])
    if (phrase in words):
        total += words[phrase]

Конечно, это решение предполагает, что во всех ваших записях есть два слова, а это не так.Чтобы решить эту проблему, включите words в словарь словарей, в котором словарь верхнего уровня сопоставляет фразу с количеством слов в нем:

words = {1: {"funny": 2}, 2: {"very funny": 3, "accidentally funny": 1}}
splitData = data.split(' \r\n')
total = 0
i = 0
while (i < len(splitData)):
    for l, mapping in words.items():
        phrase = ' '.join(splitData[i:(i + l)])
        if (phrase in mapping):
            total += mapping[phrase]
            i += 1
            continue
    i++

Обратите внимание, что я добавляю l к i чтобы избежать дубликатовОпять же, вы можете использовать кортежи вместо словаря, чтобы установить порядок поиска.Кроме того, я использую цикл while вместо forloop, потому что вы не можете изменить значение инварианта цикла внутри цикла в Python.

0 голосов
/ 13 сентября 2018

for I in data это проблема.так как данные str, вы в основном перебираете отдельные символы, а не полные слова.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...