【问题标题】:Calculating Word Proximity in an inverted Index计算倒排索引中的单词邻近度
【发布时间】:2013-10-01 13:58:15
【问题描述】:

作为搜索引擎的一部分,我开发了倒排索引。

所以我有一个包含以下类型元素的列表

public struct ForwardBarrelRecord
{
    public string DocId;
    public int hits { get; set; }
    public List<int> hitLocation;
}

现在这个记录是针对一个词的。 hitLocation 包含在文档中找到特定单词的位置。

现在我想要计算List&lt;int&gt; hitLocation 中的元素与另一个List&lt;int&gt; hitLocation 的接近程度,然后如果列表中的元素相邻,则增加两条记录的权重。

我遇到的问题是为此目的找到合适的算法。任何帮助表示赞赏

【问题讨论】:

  • 您已经有了命中位置列表,如果您以离散函数查看它们怎么办 - 您可以将每个命中转换为一个范围(以每个索引为中心并下降到两侧,总宽度取决于如何关闭你想要的话)。然后,您基本上可以通过每两个“列表”之间的点积来获得邻近分数
  • 我认为这是我需要的。虽然这是一个简明的评论,但没有得到我需要的完整答案,但我真的很感激一些关于进一步获取知识的一般指示:)
  • 好吧,不管它的价值——我在这里写了一个更详细的解释——stackoverflow.com/questions/19034271/…

标签: algorithm indexing search-engine information-retrieval inverted-index


【解决方案1】:

如果hitLocation 列表按排序顺序,这是最简单的。所以开始吧:

var word1List = word1.hitLocation.Orderby(s => s).ToList();
var word2List = word2.hitLocation.Orderby(s => s).ToList();

虽然如果您是为搜索引擎执行此操作,那么您可能希望这些列表在倒排索引中预先排序。

无论如何,一旦您对列表进行了排序,查找匹配项就很容易了。

int ix1 = 0;
int ix2 = 0;
while (ix1 < word1List.Count && ix2 < word2List.Count)
{
    int hit1 = word1List[ix1];
    int hit2 = word2List[ix2];
    if (hit1 < hit2)
    {
        if ((hit2 - hit1) == 1)
        {
            Console.WriteLine("Match at {0} and {1}", hit1, hit2);
        }
        ix1++;
    }
    else
    {
        ix2++;
    }
}          

这将定位 word1 后跟 word2 的出现。如果您还希望 word2 后跟 word1,您可以在 else 子句中进行类似的检查。

【讨论】:

  • 尽管我一直在寻找权重,但这似乎是一个很好的起点。谢谢。
【解决方案2】:
#include <iostream>
#include <list>
#include <string>
using namespace std;

struct ForwardBarrelRecord
{
    string DocId;
    int hits;
    list<int> hitLocation;
};

void merge(struct ForwardBarrelRecord& fa, struct ForwardBarrelRecord& fb)
{
    list<int>& la = fa.hitLocation;
    list<int>& lb = fb.hitLocation;
    la.sort();
    lb.sort();
    std::list<int>::iterator ita = la.begin(); 
    std::list<int>::iterator itb = lb.begin();
    while(ita != la.end() && itb != lb.end())
    {
        int loc_a = *ita;
        int loc_b = *itb;
        if (loc_a < loc_b)
        {
            if (loc_a + 1 == loc_b)
            {
                cout << "adjacent pair (" << loc_a << ", " << loc_b << ")" << endl;
            }
            ita++;
        }
        else if (loc_a > loc_b)
        {
            if (loc_b + 1 == loc_a)
            {
                cout << "adjacent pair (" << loc_a << ", " << loc_b << ")" << endl;
            }
            itb++;
        }
        else
        {
            ita++;
            itb++;
            if (ita != la.end() && *ita == loc_b + 1)
            {
                cout << "adjacent pair (" << *ita << ", " << loc_b << ")" << endl;
            }
            if (itb != lb.end() && *itb == loc_a + 1)
            {
                cout << "adjacent pair (" << loc_a << ", " << *itb << ")" << endl;
            }
        }
    }
}

int main() {
    struct ForwardBarrelRecord fa;
    fa.hitLocation.push_back(1);
    fa.hitLocation.push_back(2);
    fa.hitLocation.push_back(3);
    struct ForwardBarrelRecord fb;
    fb.hitLocation.push_back(2);
    fb.hitLocation.push_back(3);
    merge(fa, fb);
    return 0;
}

请参考代码在 2 个排序列表的合并扫描中输出所有相邻的命中位置。

【讨论】:

  • 您能否更详细地解释一下您的答案?
猜你喜欢
  • 2017-08-17
  • 2011-06-28
  • 1970-01-01
  • 1970-01-01
  • 2014-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-01-10
相关资源
最近更新 更多