Страницы

Поиск по вопросам

среда, 11 декабря 2019 г.

Частота слов в тексте

#python #php #bash #perl


Ниже приведенный скрипт на Python подсчитывает частоту слов в тексте (непрерывных
последовательностей букв за исключением знаков препинания) и выводит таблицу результатов. 

Работает правильно. Вопрос вот в чем: можно ли сделать то же самое проще (например,
меньше строк кода) на Python, Bash, PHP, Perl или это лучший способ?

import sys
import string

file = open(sys.argv[1], "r")
text = file.read()
file.close()

table = string.maketrans("", "")
words = text.lower().split(None)

frequencies = {}
for word in words:
    trimmed = word.translate(table, string.punctuation)
    frequencies[trimmed] = frequencies.get(trimmed, 0) + 1

keys = sorted(frequencies.keys())
for word in keys:
    print "%-32s %d" % (word, frequencies[word])

    


Ответы

Ответ 1



В вашем примере встречая подобную строку: "aa,bb,cc" она считается как "aabbcc 1", а должно быть: aa 1 bb 1 cc 1 Итак, мой вариант на Perl: #!/usr/bin/perl use strict; my %result; while (<>) { $result{ lc $_ }++ for /(\w+)/g; } printf "%-32s %d\n", $_, $result{$_} for sort keys %result; можно его конечно скомпоновать и в одну строчку. но будет нечитаемо.

Ответ 2



python, регекспы import re import sys import operator file = open(sys.argv[1], "r") text = file.read().decode("utf8") file.close() words = re.findall(r"(\w+)", text, re.UNICODE) stats = {} for word in words: stats[word] = stats.get(word, 0) + 1 stats_list = sorted(stats.iteritems(), key = operator.itemgetter(1)) for word, count in stats_list: print "%-32s %d" % (word, count)

Ответ 3



Мой вариант: #!/usr/bin/perl use strict; my %frec; sub calc{ $frec{ $1 }++ while( $_[0] =~ /\b(\S+)\b/g ); } my $fileName = shift or die( "Uasge: $0 filenameWithText" ); open FF, $fileName; calc( $_ ) for( ); foreach( sort{ $frec{$b} <=> $frec{$a} } keys %frec ){ printf( "%-32s %d\n", $_, $frec{ $_ } ); } close FF;

Ответ 4



Скрипт на bash/awk, для коллекции: #/bin/bash if [ -z "$1" ] then echo "Usage: `basename $0` filename" exit 1 fi for x in $(sed -rn 's/\W+/ /gp' $1); do echo $x done | awk '{print tolower($0)}' | sort | awk ' { if (!word) { word = $1 num = 0 } else if (word == $1) { num++ } else { print word, num+1 word = $1 num = 0 } }'

Ответ 5



Мой скромный вариант: import sys, string text = sorted(open(sys.argv[1], 'r').read().translate(string.maketrans('', ''), string.punctuation).split()) for i in range(len(text) - 1): if text[i + 1] == text[i]: continue print '%s %d' % (text[i], text.count(text[i])) для python3: import sys, string text = sorted(open(sys.argv[1]).read().lower().translate(''.maketrans('', '', string.punctuation)).split()) for i in range(len(text) - 1): if text[i + 1] == text[i]: continue print('{0:>20} {1:<}'.format((text[i]), text.count(text[i])))

Ответ 6



Подсчёт частоты слов с поддержкой Unicode (.casefold(), \w+): текст, в кодировке из локали, задаётся из файлов, указанных в командной строке, или со стандартного ввода (если не указаны) слова выводятся в порядке убывания популярности кодировка для вывода может отличаться от кодировки на входе выводит построчно, с указанным в вопросе форматированием (ширина под слово — 32 символа) #!/usr/bin/env python3 import fileinput import re from collections import Counter words = (word for line in fileinput.input() for word in re.findall(r'\w+', line.casefold())) for word, count in Counter(words).most_common(): print("%-32s %d" % (word, count)) Вот версия, близкая к поведению Питон 2 кода из вопроса: читает байты из файла, переводит их в нижний регистр, разбивает на слова по стандартному пробелу (не поддерживает Unicode) удаляет ascii пунктуацию из каждого слова (может пустая строка остаться) считает получившиеся слова, сортирует их по величине байт выводит построчно, с указанным в вопросе форматированием (ширина под слово — 32 байта) #!/usr/bin/env python3 import os import string import sys from collections import Counter from pathlib import Path words = Path(sys.argv[1]).read_bytes().lower().split() chars_to_trim = string.punctuation.encode() trimmed = (word.translate(None, chars_to_trim) for word in words) for word, count in sorted(Counter(trimmed).items()): sys.stdout.buffer.write(b"%-32s %d%s" % (word, count, os.linesep.encode())) Два примера разный вывод генерируют как правило.

Ответ 7



Можно воспользоваться модулем nltk, который предназначен для работы с естественными текстами: In [54]: from nltk import word_tokenize, FreqDist In [55]: data = open(r'c:/temp/TWAIN.LOG').read() In [56]: fdist = FreqDist(word.lower() for word in word_tokenize(data) if word.isalpha()) 10 наиболее часто встречающихся слов: In [57]: fdist.most_common(10) Out[57]: [('message', 10), ('ctwtrace', 4), ('ctwunk', 3), ('dsm', 3), ('dsmentrydiagexit', 3), ('rc', 3), ('cc', 3), ('thunker', 2), ('scannerredirection', 2), ('to', 2)] весь словарь целиком: In [58]: dict(fdist) Out[58]: {'message': 10, 'ctwunk': 3, 'reset': 1, 'log': 1, 'starting': 1, 'thunker': 2, 'why': 1, 'ca': 1, 'we': 1, 'find': 1, 'the': 1, 'window': 1, 'dsm': 3, 'dsmentrydiagexit': 3, 'rc': 3, 'cc': 3, 'ctwtrace': 4, 'scannerredirection': 2, 'to': 2, 'null': 2, 'control': 2, 'identity': 2, 'getfirst': 1, 'getnext': 1}

Ответ 8



Php вариант частоты вхождений слов в тексте: $text = preg_replace("/[\s\.\,\!]+/", " ", $text); $text = explode(" ", $text); foreach (array_count_values($text) as $key => $value) { echo '
'.$key.'-->'.$value; }

Комментариев нет:

Отправить комментарий