Подсчет общей суммы каждого значения в одном столбце с другим в Perl - PullRequest
1 голос
/ 18 февраля 2011

У меня есть данные с разделителями табуляции с несколькими столбцами.

У меня есть имена ОС в столбце 31 и байты данных в столбцах 6 и 7. Я хочу подсчитать общий объем каждой уникальной ОС.

Итак, я сделал что-то в Perl, как это:

#!/usr/bin/perl
use warnings;

my @hhfilelist  = glob "*.txt";
my %count = ();

for my $f (@hhfilelist) {
    open F, $f || die "Cannot open $f: $!";
    while (<F>) {
        chomp;
        my @line = split /\t/;
        # counting volumes in col 6 and 7 for 31
        $count{$line[30]} = $line[5] + $line[6];     
    }
    close (F);
}

my $w = 0;

foreach $w (sort keys %count) {
    print "$w\t$count{$w}\n";
}

Итак, результат будет примерно таким:

Windows    100000
Linux        5000
Mac OSX     15000
Android      2000

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

Что я делаю не так?

Ответы [ 3 ]

6 голосов
/ 18 февраля 2011

Похоже, что вы на самом деле не суммируете счет - вы перезаписываете последний счет для любой ОС на счетчик из последней строки для этой ОС.

$count{$line[30]} = $line[5] + $line[6];

Должно быть

$count{$line[30]} += $line[5] + $line[6];

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

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

     open(my $filehandle, "<", $f) || die "Cannot open $f: $!";
    
  2. Если вы на 100% уверены, что ваш файл не содержит указанных значений полей или вкладок в содержимом поля, ваша логика на основе split в порядке. Для действительно сложных X-файлов я настоятельно рекомендую использовать Text::CSV_XS / Text::CSV CPAN модуль

  3. Не нужно инициализировать переменные %count или $w - хэш автоматически инициализируется для пустого хэша, а $w присваивается в качестве переменной цикла - вы можете фактически объявить его в цикле сам: foreach my $w (sort keys %count) {

  4. Пожалуйста, не используйте 1-буквенные переменные. $w не имеет смысла в последнем цикле, тогда как $os_name ясно.

3 голосов
/ 18 февраля 2011

Ваше выражение лица

open F, $f || die "Cannot open $f: $!";
У

есть небольшая ошибка, которая в конечном итоге укусит вас, хотя, вероятно, не сегодня.

Оператор || имеет более высокий приоритет, чем оператор запятой слева от него, поэтому это выражение фактически анализируется как

open F, ($f || die "Cannot open $f: $!")

То есть, вы будете die, когда $f имеет ложное (0, "" или undef) значение, а не тогда, когда инструкция open не сможет открыть файл с заданным именем $f.

Чтобы сделать то, что вы имеете в виду, вы можете использовать круглые скобки:

open (F, $f) || die ...

или используйте альтернативный оператор с низким приоритетом or

open F, $f  or  die ...

( Иногда я сам себя укусил )

2 голосов
/ 18 февраля 2011
$count{$line[30]} = $line[5] + $line[6];

следует использовать оператор + =, чтобы добавить сумму строки к итоговой сумме, а не устанавливать как итоговую сумму:

$count{$line[30]} += $line[5] + $line[6];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...