Поиск нормального запроса в инвертированном индексе - PullRequest
1 голос
/ 15 октября 2010

У меня есть полный инвертированный индекс в виде словаря вложенных питонов.Его структура:

{word: {doc_name: [location_list]}}

Например, пусть словарь будет называться индексом, а затем для слова «спам»,запись будет выглядеть так:

{spam: {doc1.txt: [102,300,399], doc5.txt: [200,587]}}

, так что документы, содержащие любое слово, могут быть заданы index [word] .keys () , и частота в этом документе len (index [word] [document])

Теперь мой вопрос: какЯ реализую обычный запрос поиска в этом индексе.т. е. данный запрос, содержащий, скажем, 4 слова, находит документы, содержащие все четыре совпадения (ранжированные по общей частоте появления), затем документы, содержащие 3 совпадения и т. д.

**

Добавил этот код, используя ответ С. Лотта.Это код, который я написал.Он работает точно так, как я хочу, (нужно только некоторое форматирование вывода), но я знаю, что это можно улучшить.

**

from collections import defaultdict
from operator import itemgetter

# Take input

query = input(" Enter the query : ")

# Some preprocessing

query = query.lower()
query = query.strip()

# now real work

wordlist = query.split()
search_words = [ x for x in wordlist if x in index ]    # list of words that are present in index.

print "\nsearching for words ... : ", search_words, "\n"

doc_has_word = [ (index[word].keys(),word) for word in search_words ]
doc_words = defaultdict(list)
for d, w in doc_has_word:
    for p in d:
        doc_words[p].append(w)

# create a dictionary identifying matches for each document    

result_set = {}

for i in doc_words.keys():
    count = 0
    matches = len(doc_words[i])     # number of matches
    for w in doc_words[i]:
        count += len(index[w][i])   # count total occurances
    result_set[i] = (matches,count)

# Now print in sorted order

print "   Document \t\t Words matched \t\t Total Frequency "
print '-'*40
for doc, (matches, count)) in sorted(result_set.items(), key = itemgetter(1), reverse = True):
    print doc, "\t",doc_words[doc],"\t",count

Просьба комментировать .... Спасибо.

Ответы [ 3 ]

3 голосов
/ 15 октября 2010

Вот начало:

doc_has_word = [ (index[word].keys(),word) for word in wordlist ]

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

Но

from collections import defaultdict
doc_words = defaultdict(list)
for d, w in doc_has_word:
    doc_words[tuple(d.items())].append(w)

Может быть полезно.

0 голосов
/ 16 октября 2010

Вот решение для поиска похожих документов (самая сложная часть):

wordList = ['spam','eggs','toast'] # our list of words to query for
wordMatches = [index.get(word, {}) for word in wordList]
similarDocs = reduce(set.intersection, [set(docMatch.keys()) for docMatch in wordMatches])

wordMatches получает список, в котором каждый элемент является словарем документа, совпадающим для одного из сопоставляемых слов.

similarDocs - это набор документов, содержащий все слова, для которых запрашивается.Это достигается путем извлечения только имен документов из каждого словаря в списке wordMatches, представления этих списков имен документов в виде наборов, а затем пересечения наборов для поиска общих имен документов.

Однаждывы нашли документы, которые похожи, вы должны быть в состоянии использовать defaultdict (как показано в ответе С. Лотта), чтобы добавить все списки совпадений для каждого слова и каждого документа.

Ссылки по теме:

0 голосов
/ 15 октября 2010
import itertools

index = {...}

def query(*args):
    result = []

    doc_count = [(doc, len(index[word][doc])) for word in args for doc in index[word]]
    doc_group = itertools.groupby(doc_count, key=lambda doc: doc[0])

    for doc, group in doc_group:
        result.append((doc, sum([elem[1] for elem in group])))

    return sorted(result, key=lambda x:x[1])[::-1]
...