袋子词代表问题

时间:2010-03-05 01:23:40

标签: c# .net-3.5

基本上我有一个字典,其中包含我的词汇表中的所有单词作为键,并且所有单词都以0作为值。

要将文档处理成一个单词表示,我用相应的IEqualityComparer复制该字典,然后检查字典是否包含文档中的每个单词并增加它的密钥。

要获得单词表示的数组,我只需使用ToArray方法。

这似乎工作正常,但我只是被告知字典不能保证相同的键顺序,因此结果数组可能代表不同顺序的单词,使其无用。

我目前解决此问题的想法是将单词字典的所有键复制到ArrayList中,创建适当大小的数组,然后使用数组列表的indexOf方法填充数组。

所以我的问题是,有没有更好的方法来解决这个问题,我看起来有点粗糙......而且由于IEqualityComparer,我不会有问题吗?

6 个答案:

答案 0 :(得分:4)

让我看看我是否理解这个问题。您有两个文档D1和D2,每个文档包含从已知词汇表{W1,W2 ... Wn}中提取的单词序列。您希望获得两个映射,指示每个文档中每个单词的出现次数。所以对于D1,你可能有

W1 --> 0
W2 --> 1
W3 --> 4

表示D1可能是“W3 W2 W3 W3 W3”。也许D2是“W2 W1 W2”,所以它的映射是

W1 --> 1
W2 --> 2
W3 --> 0

您希望同时采用两个映射并确定向量[0,1,4]和[1,2,0],然后计算这些向量之间的角度,以确定两个文档的相似或不同。

您的问题是字典不保证以任何特定顺序枚举键/值对。

好的,所以订购它们。

vector1 = (from pair in map1 orderby pair.Key select pair.Value).ToArray();
vector2 = (from pair in map2 orderby pair.Key select pair.Value).ToArray();

你已经完成了。

这会解决您的问题,还是我误解了这种情况?

答案 1 :(得分:2)

如果我理解正确,您希望按字频拆分文档。

您可以获取文档并在其上运行正则表达式以拆分单词:

var words=Regex
    .Matches(input,@"\w+")
    .Cast<Match>()
    .Where(m=>m.Success)
    .Select(m=>m.Value);

制作频率图:

var map=words.GroupBy(w=>w).Select(g=>new{word=g.Key,freqency=g.Count()});

如果这很重要,GroupBy方法有一些重载允许你提供另一个IEqualityComparer。

阅读您的评论,创建相应的频率序列:

map.Select(a=>a.frequency)

此序列的顺序与上面的序列map完全相同。

这有什么帮助吗?

答案 2 :(得分:1)

还有OrderedDictionary

  

表示键/值的集合   密钥可访问的对   或指数。

答案 3 :(得分:0)

这样的东西可能会起作用,虽然它绝对是丑陋的,我相信它与你的建议相似。 GetWordCount()完成工作。

  

类WordCounter       {

     

public Dictionary dictionary = new Dictionary();

    public void CountWords(string text)
    {
        if (text != null && text != string.Empty)
        {
            text = text.ToLower();
            string[] words = text.Split(' ');
            if (dictionary.ContainsKey(words[0]))
            {
                if (text.Length > words[0].Length)
                {
                    text = text.Substring(words[0].Length + 1);
                    CountWords(text);
                }

            }
            else
            {
                int count = words.Count(
                    delegate(string s)
                    {
                        if (s == words[0]) { return true; }
                        else { return false; }
                    });
                dictionary.Add(words[0], count);
                if (text.Length > words[0].Length)
                {
                    text = text.Substring(words[0].Length + 1);
                    CountWords(text);
                }

            }
        }
    }

    public int[] GetWordCount(string text)
    { 
        CountWords(text);
        return dictionary.Values.ToArray<int>();
    }


}

答案 4 :(得分:0)

这会对您有所帮助:

SortedDictionary<string, int> dic = new SortedDictionary<string, int>();

            for (int i = 0; i < 10; i++)
            {
                if (dic.ContainsKey("Word" + i))
                    dic["Word" + i]++;
                else
                    dic.Add("Word" + i, 0);
            }

            //to get the array of words:
            List<string> wordsList = new List<string>(dic.Keys);
            string[] wordsArr = wordsList.ToArray();

            //to get the array of values
            List<int> valuesList = new List<int>(dic.Values);
            int[] valuesArr = valuesList.ToArray();

答案 5 :(得分:0)

如果您要做的只是计算余弦相似度,则无需将数据转换为20,000个长度的数组,尤其是考虑到数据可能很稀疏,大多数条目为零。

处理文件时,将文件输出数据存储到键入字词的字典中。然后计算点积和幅度,迭代完整单词列表中的单词,在每个文件ouptut数据中查找单词,如果存在则使用找到的值,如果不存在,则使用零。