Python: Как найти строку с большинством совпадений в списке строк - PullRequest
2 голосов
/ 14 марта 2012

Я постараюсь подробно объяснить, что мне нужно:

Я разбираю RSS-канал в Python, используя feedparser. Этот канал, конечно же, содержит список элементов с заголовком, ссылкой и описанием, как обычный канал RSS.

С другой стороны, у меня есть список строк с некоторыми ключевыми словами, которые мне нужно найти в описании товара.

Что мне нужно сделать, это найти элемент, который имеет наибольшее количество соответствий ключевых слов

Пример:

RSS-лента

<channel>
    <item>
        <title>Lion</title>
        <link>...</link>
        <description>
            The lion (Panthera leo) is one of the four big cats in the genus 
            Panthera, and a member of the family Felidae.
        </description>
    </item>
    <item>
        <title>Panthera</title>
        <link>...</link>
        <description>
            Panthera is a genus of the Felidae (cats), which contains 
            four well-known living species: the tiger, the lion, the jaguar, and the leopard.
        </description>
    </item>
    <item>
        <title>Cat</title>
        <link>...</link>
        <description>
            The domestic cat is a small, usually furry, domesticated, 
            carnivorous mammal. It is often called the housecat, or simply the 
            cat when there is no need to distinguish it from other felids and felines.
        </description>
    </item>
</channel>

Список ключевых слов

['cat', 'lion', 'panthera', 'family']

Таким образом, в этом случае элемент с наибольшим (уникальным) соответствием является первым, потому что он содержит все 4 ключевых слова (не важно, что он говорит «кошки» вместо просто «кошка», мне просто нужно найти ключевое слово внутри строки)

Позвольте мне уточнить, что даже если какое-то описание содержало ключевое слово «кошка» 100 раз (и ни одно из других ключевых слов), это не будет победителем, потому что я ищу большинство содержащихся ключевых слов, а не большинство раз. появляется ключевое слово.

Прямо сейчас я зацикливаюсь на элементах rss и делаю это "вручную", подсчитывая время появления ключевого слова (но у меня возникла проблема, упомянутая в предыдущем абзаце).

Я очень новичок в Python, и я из другого типа языка (C #), поэтому извините, если это довольно тривиально.

Как бы вы подошли к этой проблеме?

Ответы [ 2 ]

3 голосов
/ 14 марта 2012
texts = [ "The lion (Panthera leo) ...", "Panthera ...", "..." ]
keywords  = ['cat', 'lion', 'panthera', 'family']

# gives the count of `word in text`
def matches(text):
    return sum(word in text.lower() for word in keywords)

# or inline that helper function as a lambda:
# matches = lambda text:sum(word in text.lower() for word in keywords)

# print the one with the highest count of matches
print max(texts, key=matches)
0 голосов
/ 14 марта 2012

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

  • Частичное совпадение слов - должно ли 'cat' совпадать с 'concatenate'? Как насчет "кошек"?
  • Чувствительность к регистру - должно ли 'cat' соответствовать 'CAT'? как насчет "кота"?

Мое решение, приведенное ниже, учитывает оба этих случая.

import re

test_text = """
Cat?

The domestic cat is a small, usually furry, domesticated, 
carnivorous mammal. It is often called the housecat, or simply the 
cat when there is no need to distinguish it from other felids and felines.
"""

wordlist = ['cat','lion','feline']
# Construct regexp like r'\W(cat|lionfeline)s?\W'
# Matches cat, lion or feline as a whole word ('cat' matches, 'concatenate'
# does not match)
# also allow for an optional trailing 's', so that both 'cat' and 'cats' will
# match.
wordlist_re = r'\W(' + '|'.join(wordlist) + r')(s?)\W'

# Get list of all matches from text. re.I means "case insensitive".
matches = re.findall(wordlist_re, test_text, re.I)

# Build list of matched words. the `[0]` means first capture group of the regexp
matched_words = [ match[0].lower() for match in matches]

# See which words occurred
unique_matched_words = [word for word in wordlist if word in matched_words]

# Count unique words
num_unique_matched_words = len(unique_matched_words)

Вывод выглядит так:

>>> wordlist_re
'\\W(cat|lion|feline)(s?)\\W'
>>> matches
[('Cat', ''), ('cat', ''), ('cat', ''), ('feline', 's')]
>>> matched_words
['cat', 'cat', 'cat', 'feline']
>>> unique_matched_words
['cat', 'feline']
>>> num_unique_matched_words
2
>>> 
...