подсчитать количество ключей, которые сопоставляются со значением

У меня есть следующий хэш

my %hash = (
    w1 => '0',
    e2 => '1',
    r1 => '2',
    o3 => '1',
    h4 => '0',
    t5 => '1',
);

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

3 keys map to value 1.
1 key map to value 2.
2 keys map to value 0.

Я хотел бы сделать это без использования функции из модуля.

Один из способов, которым я думал сделать это, - это перебирать значения хэша. Если у этого значения есть ключ, увеличьте счетчик для этого ключа. Проблема заключается в том, чтобы заранее знать значения, чтобы я мог инициализировать счетчики для каждого значения. Там, вероятно, более простое решение для этого. Я думаю, что регулярное выражение может работать.

попытка 1

my $string;
foreach my $value (value %hash) {
$string = join(",", $value);
}

# count the number of occurrences for each value (separated by commas)

person cooldood3490    schedule 19.04.2013    source источник


Ответы (2)


Используйте другой хэш для подсчета вхождений.

#!/usr/bin/perl
use warnings;
use strict;

my %hash = (
    w1 => '0',
    e2 => '1',
    r1 => '2',
    o3 => '1',
    h4 => '0',
    t5 => '1',
);

my %count;
for my $value (values %hash) {
    $count{$value}++;
}

for my $value (keys %count) {
    my $count = $count{$value};

    print "$count key", $count == 1 ? q() : 's',
          " map",       $count == 1 ? 's' : q(),
          " to $value.\n";
}
person choroba    schedule 19.04.2013
comment
Можете ли вы объяснить синтаксис в операторе печати? Например, что такое ?, q() и 's'? Для чего :? - person cooldood3490; 20.04.2013
comment
q() — пустая строка. condition ? true : false — это тернарный оператор, если условие истинно, оно возвращает истинную часть, в противном случае — ложную. В этом случае он обрабатывает грамматику. - person choroba; 20.04.2013

Вы можете перебрать хэш:

my %counterhash = ();

while ( ($key, $value) = each %hash )
{
  #print "key: $key, value: $hash{$key}\n";
  $counterhash{$value}++;
}

После этого counterhash будет хэшем каждого значения до количества вхождений этого значения.

Вам не нужно инициализировать ключ каждого конкретного $value. Изначально он не определен, но при увеличении интерпретируется как ноль.

В документации говорится:

Единственное, что вам нужно объявить в Perl, это форматы отчетов и подпрограммы (а иногда даже не подпрограммы). Переменная содержит неопределенное значение ("undef") до тех пор, пока ей не будет присвоено определенное значение, которое отличается от "undef". При использовании в качестве числа "undef" рассматривается как 0; при использовании в виде строки она рассматривается как пустая строка, ""; и при использовании в качестве ссылки, которой не назначено, это рассматривается как ошибка.

person ronalchn    schedule 19.04.2013
comment
это тоже работает. можете ли вы показать, как вы инициализируете $key и $value? Когда я делаю while ( my ($key, $value) = each %hash) {...}, у меня это не работает. Я получаю синтаксические ошибки. - person cooldood3490; 20.04.2013
comment
не уверен, я скопировал его с perlhowto.com/iterate_through_a_hash, потому что на самом деле я не программирую на Perl , поэтому я не знаком с синтаксисом - person ronalchn; 20.04.2013
comment
LOL, в конце концов, вы опубликовали решение, которое работает! +1, я уверен, что у вас будет больше очков - person cooldood3490; 20.04.2013