Что нового

[Массивы] Кто нибудь делал подсчитывание частоты слов в текстовом файле

vaf

Новичок
Сообщения
190
Репутация
2
Доброе утро уважаемые форумчане. Возникла такая задача.
Есть текстовый файл (несколько десятков тысяч слов), в котором необходимо подсчитать и вывести слова и частоту их повторения. Ну скажем Top 100 самых часто повторяемых слов.
С моими знаниями в AutoIt, я бы брал последовательно каждое слово и делал цикл на весь файл в поисках повторений, но это наверное слишком долго. может есть какое то более изящное решение проблемы ?
 

WSWR

AutoIT Гуру
Сообщения
941
Репутация
363
vaf

Быстро, скорее всего, не получится :smile:

Код:
#include <Array.au3>

$sFilePath = FileOpenDialog('', @ScriptDir & '\', 'Файлы (*.txt)', 1)
If @error <> 0 Then Exit

$text = FileRead($sFilePath)
$text = StringRegExpReplace($text, '[[:punct:]]', '')
$aList = StringSplit($text, ' ', 1)

$sText = ''
For $i = 1 To $aList[0]
	Assign($aList[$i] & '/\', Eval($aList[$i] & '/\') + 1)
	If Eval($aList[$i] & '/\') = 1 And StringLen($aList[$i]) > 2 And StringIsDigit($aList[$i]) = 0 Then $sText &= $aList[$i] & '_'
Next

$aList = StringSplit(StringTrimRight($sText, 1), '_')
;_ArrayDisplay($aList)

_ArrayDelete($aList, 0)

Dim $array[UBound($aList)][2]

For $i = 1 To UBound($aList) - 1
	StringReplace($text, $aList[$i], '')
	$array[$i][1] = $aList[$i]
	$array[$i][0] = @extended
Next
_ArraySort($array, 1, 0, 0, 0)

_ArrayDisplay($array)
 

Suppir

Продвинутый
Сообщения
967
Репутация
62
Если нужно максимально быстро сделать, то вот на Perl решение:

Код:
use locale; use POSIX; &POSIX::setlocale(&POSIX::LC_ALL, "ru_Ru.CP1251"); use Encode;

open(IN, "10.txt");
open(OU, ">result.txt");
while(<IN>){
	while(/([а-я]{3,})/gi){$hash{$1}++}
}

foreach $x (sort {$hash{$b}<=>$hash{$a}} keys %hash)
{
	$c == 100 ? exit : $c++;
	print OU "$x - $hash{$x}\n";
}
На AutoIt можно подобным способом переписать, только использовать библиотеку для хешей.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
vaf,
Можно так попробовать. У меня файл 449 КБ (прикреплен) обрабатывает чуть дольше 3 сек.
Код:
#include <Array.au3>

$iStart = TimerInit()
$sText = FileRead(@ScriptDir & '\10.txt')

$aTemp = StringRegExp('Вася ' & $sText, '([а-яА-ЯёЁ]{4,})', 3);or '([а-яА-ЯёЁ]{3,})'
If @error Then Exit 13
$aTemp[0] = UBound($aTemp) - 1
ConsoleWrite('All: ' & $aTemp[0] & @LF)

Dim $aText[$aTemp[0] + 1][2] = [[$aTemp[0]]]
_1()
Dim $aUniq[$aText[0][0] + 1][2]
_2()
ConsoleWrite('Uniq: ' & $aUniq[0][0] & @LF)
_ArraySort($aUniq, 1, 1, 0, 1)
ReDim $aUniq[101][2]
$aUniq[0][0] = 100
ConsoleWrite(StringFormat('%.2f sec', TimerDiff($iStart) / 1000) & @LF)
_ArrayDisplay($aUniq)

Func _2()
	For $i = $aText[0][0] To 1 Step -1
		Assign($aText[$i][0], Eval($aText[$i][0]) + 1)
		If Eval($aText[$i][0]) = 1 Then
			$aUniq[0][0] += 1
			For $j = 0 To 1
				$aUniq[$aUniq[0][0]][$j] = $aText[$i][$j]
			Next
		EndIf
	Next
	$aText = 0
	ReDim $aUniq[$aUniq[0][0] + 1][2]
EndFunc   ;==>_2

Func _1()
	For $i = 1 To $aTemp[0]
		$aText[$i][0] = $aTemp[$i]
		Assign($aText[$i][0], Eval($aText[$i][0]) + 1)
		$aText[$i][1] = Eval($aText[$i][0])
	Next
	$aTemp = 0
EndFunc   ;==>_1
 

WSWR

AutoIT Гуру
Сообщения
941
Репутация
363
Только мне кажется, что эта функция в примере от madmasles подходит для быстрого определения количества групп уникальных элементов практически в любом массиве (одномерном) и вполне достойна для включения в Array.au3? :laugh:
 
Автор
V

vaf

Новичок
Сообщения
190
Репутация
2
madmasles Огромный респектще. Файл 1.5 Мб обработал за несколько секунд, отличный результат
 

Suppir

Продвинутый
Сообщения
967
Репутация
62
vaf [?]
Файл 1.5 Мб обработал за несколько секунд, отличный результат

OffTopic:
Ребята, при всем уважении, скрипт на Perl работает на порядок быстрее (0,5 секунд против 6 секунд). На c# или python время будет около секунды. Т.е. если у вас не 1,5 мегабайт, а 1,5 гигабайта нужно распарсить, то лучше использовать языки, оптимизированные под обработку текста.

Чтобы не быть голословным, запустил оба скрипта в скайте:
http://smotr.im/8zYW

 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
madmasles,
Это полный ... восторг!!!
:thumbs_up:
Я не успокоился пока не разобрал полностью каждую строчку.
В некоторых местах можно охренеть просто!
Вот как с этим разобраться?
Код:
StringRegExp('Вася ' & $sText, '([а-яА-ЯёЁ]{4,})', 3)

http://autoit-script.ru/autoit3_docs/functions/StringRegExp.htm
Код:
{ } начало и конец повторителей, например {3,8}
:shok:
Хорошо что есть английская справка
Код:
{x,} Repeat the previous character, set or group at least x times.

Но самое главное - это, конечно же, фокус с Assign и Eval.
Прямое нагибание интерпретатора. :laugh:

Скрипт, я конечно же переписал.
Не с целью посоревноваться с madmasles, а чтобы понять как это работает (хотя и добился скорости большей процентов на 10-15). :-[
Код:
#include <Array.au3>

$iStart = TimerInit()
$sText = FileRead(@ScriptDir & '\10.txt')

$aTemp = StringRegExp('Вася ' & $sText, '([a-zA-Zа-яА-ЯёЁ]{4,})', 3);or '([а-яА-ЯёЁ]{3,})'
If @error Then Exit 13
$aTemp[0] = UBound($aTemp) - 1

For $i = 1 To $aTemp[0]
	Assign($aTemp[$i], Eval($aTemp[$i])+1 )
Next

Dim $uArray[$aTemp[0]][2]=[[0]]

For $i = 1 To $aTemp[0]
	If Eval($aTemp[$i]) > 0 Then
		$uArray[0][0]+= 1
		$uArray[$uArray[0][0]][0] = $aTemp[$i]
		$uArray[$uArray[0][0]][1] = Eval($aTemp[$i])
		Assign($aTemp[$i], -1)
	EndIf
Next

ReDim $uArray[$uArray[0][0]+1][2]

_ArraySort($uArray, 1, 1, 0, 1)
ReDim $uArray[101][2]
$uArray[0][0] = 100
ConsoleWrite(StringFormat('%.2f sec', TimerDiff($iStart) / 1000) & @LF)
_ArrayDisplay($uArray)

madmasles, круто неимоверно!
:thumbs_up: :IL_AutoIt_1:

OffTopic:
Suppir, шел бы ты тусоваться в песочнице по перлу.
Вот это я сейчас IT-шникам скажу: "поставьте мне Perl"... Так мне ж завтра начнут задачи какие-то подкидывать - наваять фигню какю-то. Нафиг оно мне надо?!
:beach:
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
:IL_AutoIt_2:

madmasles,
А с твоим скриптом я помучился... Пока не дошло что Assign в теле функци приравнивается к локальной переменной и из основного скрипта она не видна.
:wall_brake:
 

C2H5OH

AutoIT Гуру
Сообщения
1,473
Репутация
333
Да, я до того места не дочитал. :-[
Нашел первое описание {}, ничего из него не понял и полез в английскую справку.
 

Suppir

Продвинутый
Сообщения
967
Репутация
62
C2H5OH [?]
шел бы ты тусоваться в песочнице по перлу.
OffTopic:

По перлу нет песочниц. Язык исчезающий - остались только динозавры. О регулярных выражениях читай книгу Джеффри Фридла.
Кстати, чтобы ты знал, в autoit, python, ruby, php, c#, d, c++2011, java и т.д. используются регулярные выражения Perl (PCRE-подобные).
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
vaf,
[info border=#0000ff float=left]На форуме принято помечать тему решенной после получения ответа на свой вопрос!
Вверху или внизу темы нажмите на ссылку такого вида:
package_old.gif
Тема не решена
[/info]
 

johnmarshall

Осваивающий
Сообщения
192
Репутация
35
madmasles
не скачивается прикрепленный файл:
Ошибка!
Вы не можете зайти в этот раздел
 
Верх