Рассчитать частоту символов в сообщении с помощью Perl - PullRequest
4 голосов
/ 16 октября 2011

Я пишу Perl Script, чтобы узнать частоту появления символов в сообщении.Вот логика, которой я придерживаюсь:

  • Читайте по одному символу за раз из сообщения с помощью getc () и сохраняйте его в массив.
  • Запуск цикла for, начиная с индексаОт 0 до длины этого массива.
  • Этот цикл будет считывать каждый символ массива и присваивать ему временную переменную.
  • Запускать другой цикл, вложенный в приведенный выше цикл, который будет выполняться изиндекс тестируемого символа до длины массива.
  • Используя сравнение строк между этим символом и текущим массивом, индексированным символом, счетчик увеличивается, если они равны.
  • После завершения внутреннего цикла, я печатаю частоту символав целях отладки.

Вопрос: Я не хочу, чтобы программа пересчитывала частоту символа, если она уже была вычислена.Например, если символ «а» встречается 3 раза, то при первом запуске вычисляется правильная частота.Однако при следующем появлении «a», поскольку цикл выполняется от этого индекса до конца, частота равна (фактическая частота -1).Аналогично для третьего случая частота (фактическая частота -2).

Чтобы решить эту проблему.Я использовал другой временный массив, в который я помещал бы символ, частота которого уже была оценена.

И затем при следующем запуске цикла for перед входом во внутренний цикл for я сравниваю текущий символ с массивомоценил символы и установил флаг.На основании этого флага запускается внутренний цикл for.

Это не работает для меня.Все те же результаты.

Вот код, который я написал для достижения вышеупомянутого:

#!/usr/bin/perl

use strict;
use warnings;

my $input=$ARGV[0];
my ($c,$ch,$flag,$s,@arr,@temp);

open(INPUT,"<$input");

while(defined($c = getc(INPUT)))
{
push(@arr,$c);
}

close(INPUT);

my $length=$#arr+1;

for(my $i=0;$i<$length;$i++)
{
$count=0;
$flag=0;
$ch=$arr[$i];
foreach $s (@temp)
{
    if($ch eq $s)
    {
        $flag = 1;
    }
}
if($flag == 0)
{
for(my $k=$i;$k<$length;$k++)
{
    if($ch eq $arr[$k])
    {
        $count = $count+1;
    }
}
push(@temp,$ch);
print "The character \"".$ch."\" appears ".$count." number of times in the         message"."\n";
}
}

Ответы [ 5 ]

4 голосов
/ 16 октября 2011

Вы делаете свою жизнь намного сложнее, чем нужно. Используйте хеш:

my %freq;

while(defined($c = getc(INPUT)))
{
  $freq{$c}++;
}

print $_, " ", $freq{$_}, "\n" for sort keys %freq;

$freq{$c}++ увеличивает значение, сохраненное в $freq{$c}. (Если он был не установлен или равен нулю, он становится равным единице.)

Строка печати эквивалентна:

foreach my $key (sort keys %freq) {
  print $key, " ", $freq{$key}, "\n";
}
3 голосов
/ 16 октября 2011

Если вы хотите выполнить подсчет одного символа для всего файла, используйте любой из предложенных методов, опубликованных другими. Если вы хотите считать все вхождения каждого символа в файле, то я предлагаю:

#!/usr/bin/perl

use strict;
use warnings;

# read in the contents of the file
my $contents;
open(TMP, "<$ARGV[0]") or die ("Failed to open $ARGV[0]: $!");
{
    local($/) = undef;
    $contents = <TMP>;
}
close(TMP);

# split the contents around each character
my @bits = split(//, $contents);

# build the hash of each character with it's respective count
my %counts = map { 
    # use lc($_) to make the search case-insensitive
    my $foo = $_; 

    # filter out newlines
    $_ ne "\n" ? 
        ($foo => scalar grep {$_ eq $foo} @bits) :
        () } @bits;

# reverse sort (highest first) the hash values and print
foreach(reverse sort {$counts{$a} <=> $counts{$b}} keys %counts) {
    print "$_: $counts{$_}\n";
}
1 голос
/ 16 октября 2011

В качестве однострочника:

perl -F"" -anE '$h{$_}++ for @F; END { say "$_ : $h{$_}" for keys %h }' foo.txt
1 голос
/ 16 октября 2011

Я не понимаю проблему, которую вы пытаетесь решить, поэтому я предлагаю более простой способ подсчета символов в строке:

$string = "fooooooobar";
$char = 'o';
$count = grep {$_ eq $char} split //, $string;
print $count, "\n";

Это печатает количество вхождений $ char в $ string (7). Надеюсь, это поможет написать более компактный код

1 голос
/ 16 октября 2011

Более быстрое решение:

@result = $subject =~ m/a/g; #subject is your file

print "Found : ", scalar @result, " a characters in file!\n";

Конечно, вы можете поместить переменную вместо 'a' или даже лучше выполнить эту строку для любых символов, которые вы хотите посчитать вхождения.

...