字分配问题

时间:2010-11-08 01:18:07

标签: algorithm

我有一个大字的文件~100 Gb并且内存4Gb有限。我需要从这个文件中计算单词分布。现在一个选项是将其划分为块并对每个块进行排序,然后合并以计算字分布。有没有其他方法可以更快地完成?一个想法是抽样但不确定如何实现它以返回接近正确的解决方案。

由于

7 个答案:

答案 0 :(得分:3)

您可以构建一个Trie结构,其中每个叶子(和一些节点)将包含当前计数。由于单词将相互交叉,4GB应足以处理100 GB的数据。

答案 1 :(得分:2)

天真地我会建立一个哈希表,直到它达到内存中的某个限制,然后在内存中对其进行排序并将其写出来。最后,您可以对每个块进行n路合并。最多只有100/4块左右,但可能会少得多,只要有些词比其他词更常见(以及它们如何聚类)。

另一个选择是使用为此类内容构建的 trie 。字符串中的每个字符都成为256路树中的分支,而叶子上则有计数器。在网络上查找数据结构。

答案 2 :(得分:2)

如果你能原谅双关语,请“试着”这个:

public class Trie : Dictionary<char, Trie>
{
    public int Frequency { get; set; }

    public void Add(string word)
    {
        this.Add(word.ToCharArray());
    }

    private void Add(char[] chars)
    {
        if (chars == null || chars.Length == 0)
        {
            throw new System.ArgumentException();
        }

        var first = chars[0];
        if (!this.ContainsKey(first))
        {
            this.Add(first, new Trie());
        }

        if (chars.Length == 1)
        {
            this[first].Frequency += 1;
        }
        else
        {
            this[first].Add(chars.Skip(1).ToArray());
        }
    }

    public int GetFrequency(string word)
    {
        return this.GetFrequency(word.ToCharArray());
    }

    private int GetFrequency(char[] chars)
    {
        if (chars == null || chars.Length == 0)
        {
            throw new System.ArgumentException();
        }

        var first = chars[0];
        if (!this.ContainsKey(first))
        {
            return 0;
        }

        if (chars.Length == 1)
        {
            return this[first].Frequency;
        }
        else
        {
            return this[first].GetFrequency(chars.Skip(1).ToArray());
        }
    }
}

然后你可以调用这样的代码:

var t = new Trie();

t.Add("Apple");
t.Add("Banana");
t.Add("Cherry");
t.Add("Banana");

var a = t.GetFrequency("Apple"); // == 1
var b = t.GetFrequency("Banana"); // == 2
var c = t.GetFrequency("Cherry"); // == 1

您应该能够添加代码来遍历trie并返回单词及其频率的平面列表。

如果你发现这仍然会打击你的记忆限制,那么我可能会建议你“分而治之”。也许扫描所有第一个字符的源数据,然后分别对每个字符运行trie,然后在所有运行后连接结果。

答案 3 :(得分:0)

你知道你有多少不同的单词吗?如果不是很多(即十万)那么你可以流输入,确定单词并使用哈希表来保持计数。输入完成后,只需遍历结果。

答案 4 :(得分:0)

只需使用DBM文件即可。这是磁盘上的哈希。如果您使用的是更新版本,则可以使用B + Tree进行按顺序遍历。

答案 5 :(得分:0)

为什么不使用任何关系数据库?程序简单如下:

  1. 使用wordcount
  2. 创建一个表格
  3. word上创建索引。有些数据库有单词索引(f.e.Progress)。
  4. 使用单词。
  5. 在此表上SELECT
  6. 如果单词存在则增加计数器。
  7. 否则 - 将其添加到表格中。

答案 6 :(得分:0)

如果您使用的是python,则可以检查内置的iter功能。它将从您的文件中逐行读取,不会导致内存问题。你不应该“返回”这个值,而应该“屈服”它。 这是我用来读取文件并获取矢量值的示例。

def __iter__(self):  
     for line in open(self.temp_file_name):
         yield self.dictionary.doc2bow(line.lower().split())