在倒排索引中搜索普通查询

1 投票
3 回答
3528 浏览
提问于 2025-04-16 05:33

我有一个完整的倒排索引,它的形式是一个嵌套的Python字典。它的结构是:

{单词 : { 文档名 : [位置列表] } }

举个例子,假设这个字典叫做index,对于单词“spam”,它的条目看起来像这样:

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

这样的话,包含任何单词的文档可以通过index[word].keys()来获取,而在该文档中单词出现的频率可以通过len(index[word][document])来计算。

现在我的问题是,如何在这个索引中实现一个普通的查询搜索。也就是说,给定一个包含4个单词的查询,找到包含所有四个单词的文档(按出现的总频率排序),然后是包含3个单词的文档,以此类推……

**

我添加了这段代码,使用了S. Lott的回答。这是我写的代码,它的工作效果正是我想要的(只是输出格式需要一些调整),但我知道它可以改进。

**

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 个回答

0

在编程中,有时候我们需要处理一些数据,这些数据可能来自不同的地方,比如用户输入、文件或者网络请求。为了让程序能够理解这些数据,我们通常需要把它们转换成程序能处理的格式。

比如说,如果你从一个网页上获取了一些信息,这些信息可能是以文本的形式存在的。为了让程序能够使用这些信息,我们需要把它们转化为程序可以理解的对象或者变量。这个过程就叫做“解析”。

解析的过程就像是把一段话翻译成另一种语言,让不同的人都能理解。程序通过解析,把复杂的数据变得简单易用,这样我们就可以对这些数据进行操作,比如计算、存储或者显示。

在编程中,解析通常会用到一些特定的工具或者库,这些工具可以帮助我们快速而准确地完成这个过程。通过使用这些工具,我们可以节省很多时间和精力,让我们的程序更加高效。

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]
0

这里有一个找到相似文档的解决方案(这是最难的部分):

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(如 S. Lott 的回答中所示)将每个单词和每个文档的匹配列表合并在一起。

相关链接:

3

这是一个开始:

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)

这可能会有帮助。

撰写回答