Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Алгоритмы > частотный анализ слов встречающихся в файлах задан


Автор: rurik 16.10.2011, 21:26
Здравствуйте,подскажите как лучше написать алгоритм подсчета слов всех файлов в заданной директории.(пишу на Java)

т.е. необходимо пройти по всем файлам в директории(или несколько директорий или директория + файл .на входе массив адресов относительно диска С) , разбить все файлы на слова, посчитать количество раз которое встречается каждое слово и вывести все слова с их счетчиками отсортировав по значению счетчика.

подскажите как лучше построить алгоритм, общие мысли), может советы, если что то более детальное еще больше благодарен буду) чтобы он получился наиболее оптимальным, быстрее работал
  

Автор: Akina 16.10.2011, 23:10
Обычная сортировка подсчётом. Слова строить в обычное бин. дерево. Если прогнозируется значительный процент уникальных слов - возможно, параллельно строить суффиксное дерево для быстрой проверки на униакльность.

Автор: rurik 17.10.2011, 12:54
Расскажите поподробнее о том как именно строить слова в бинарное дерево

Автор: esperanto 17.10.2011, 16:21
TRIE дерево с дополнительным полем для  подсчета, имхо более подходит

Автор: Akina 17.10.2011, 16:27
Цитата(rurik @  17.10.2011,  13:54 Найти цитируемый пост)
как именно строить слова в бинарное дерево 

http://ru.wikipedia.org/wiki/B-%D0%B4%D0%B5%D1%80%D0%B5%D0%B2%D0%BE

Автор: Silent 18.10.2011, 12:37
Возможен еще вариант написать MapReduce на map'е, сразу в несколько потоков забубенить. Для примера код на C# (но кажется, где-то есть ошибочка):
Код

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;

namespace MapReduce
{
    class Program
    {
        struct elem
        {
            public string input,
                   output;
        }

        const int max_threads = 20;
        static int count_runs = 0;
        static Queue<Thread> threads = new Queue<Thread>();
        static Queue<elem> paths = new Queue<elem>();
        //static Queue<string> input   = new Queue<string>();
        //static Queue<string> output  = new Queue<string>();

        static char[] terms = { ' ', '.', ',', '?', '!', '-' };
        const string dirTXT = @"z:\TMP\txt\";    //каталог, откуда будут выдираться тексты
        const string dirDAT = @"z:\TMP\dat\";    //каталог, куда будут складываться обработанные файлы
        const string dirTMP = @"z:\TMP\tmp\";    //каталог, куда будут временно складываться файлы для обработки

        //главный поток обработки текстов
        static void Main(string[] args)
        {
            Console.WriteLine("Starting...");
            int i = 0;
            bool flag = true;
            while (!Console.KeyAvailable && flag)
            {
                FileInfo[] files = (new DirectoryInfo(dirTXT)).GetFiles("*.txt");
                int count = 0;
                foreach (FileInfo f in files)
                {
                    Thread t = new Thread(start);
                    threads.Enqueue(t);
                    elem a;
                    f.MoveTo(dirTMP + Path.GetFileName(f.FullName));
                    a.input = f.FullName;
                    a.output = dirDAT + i.ToString() + ".dat";
                    paths.Enqueue(a);
                    i++;
                    count++;
                }
                if (count != 0)
                    Console.WriteLine("Add " + count.ToString() + " files");
                //вручную запустим цикл обработки
                if (threads.Count > 0)
                {
                    lock (threads)
                        lock (paths)
                        {
                            Thread t = threads.Dequeue();
                            elem a = paths.Dequeue();
                            count_runs++;
                            t.Start(a);
                        }

                }
                if (Console.KeyAvailable) flag = Console.ReadKey().Key != ConsoleKey.Escape;
            }
        }

        /// <summary>
        /// Обработка файла input, результаты записывем в файл output
        /// </summary>
        static void start(object data)//string input, string output)
        {
            elem a = (elem)data;
            StreamReader fin = new StreamReader(a.input);
            SortedList<string, int> list = new SortedList<string, int>();
            //считаем файл в сортированный список
            while (!fin.EndOfStream)
            {
                foreach (string t in fin.ReadLine().Split(terms))
                    if (list.ContainsKey(t)) list[t]++;
                    else list.Add(t, 1);
            }
            //сбросим результат в файл
            StreamWriter fout = new StreamWriter(a.output);
            foreach (string t in list.Keys)
                fout.WriteLine(t + " " + list[t].ToString());
            fout.Close();
            fin.Close();
            FileInfo f = new FileInfo(a.input);
            f.Delete();
            Console.WriteLine(Path.GetFileName(a.input) + " -> " + Path.GetFileName(a.output));
            //удалим себя из количества выполняющихся потоков
            count_runs--;
            //и скажем, чтобы менеджер попытался запустить далее
            lock (threads)
                while ((count_runs < max_threads) && (threads.Count > 0))
                {
                    if (threads.Count > 0)
                    {
                        lock (threads)
                            lock (paths)
                            {
                                Thread t = threads.Dequeue();
                                elem obj = paths.Dequeue();
                                t.Start(obj);
                                count_runs++;
                            }
                    }
                }
        }
    }
}


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)