3

次のように、配列のハッシュがあります。

my %hash = (
  234 => ["aa", "bb", "aa", "ab", "aa"],
  235 => ["aa", "ab", "aa", "bb", "aa"],
  236 => ["bb", "aa", "aa", "aa", "bb"],
  ...
)

各値の最初の要素を調べて、の出現回数を数えようとしていますbb

たとえば、上記のハッシュでは、bb表示されている最初の要素すべてに対して 1 つのオカレンスがあります。その数 (すべての配列の 0 番目の要素にある "bb" の数) を新しい配列にプッシュしてから、次の要素のセットに移動する必要があります。

上記の例では、配列の 4 つの要素すべてをループし、. で最終的な配列を取得し(1, 1, 0, 1, 1)ます。

私はコードを正しくするのに苦労しており、同様の質問をまだ見つけていません。どんな助けでも大歓迎です。

4

4 に答える 4

5

簡単な解決策: ハッシュ値を反復処理します。値ごとに、配列のメンバーを反復処理し、必要に応じて結果の配列に 1 を追加します。

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

my %hash = (234 => [qw/aa bb aa ab aa/],
            235 => [qw/aa ab aa bb aa/],
            236 => [qw/bb aa aa aa bb/],
           );

my @result;

for my $value (values %hash) {
    my $i = 0;
    for (@$value) {
        $result[$i++] += 'bb' eq $_;
    }
}

print "@result\n";
于 2012-07-29T00:02:23.070 に答える
2

grep演算子は、特定の条件に一致するリスト内の値をカウントするための最適なツールです。ハッシュ値のリストの各エントリを反復処理して、各要素のカウントを取得します。

このコードは、各ハッシュ値配列の長さが同じであると想定し、最初の要素の長さをすべてのサイズとして使用します。

use strict;
use warnings;

my %data = (
  234 => [ qw/aa bb aa ab aa/ ],
  235 => [ qw/aa ab aa bb aa/ ],
  236 => [ qw/bb aa aa aa bb/ ],
);

my @count_bb;
for my $i ( 0 .. $#{(values %data)[0]} ) {
  $count_bb[$i] = grep { $_->[$i] eq 'bb' } values %data;
} 

print "@count_bb\n";

出力

1 1 0 1 1

この代替手段は、ハッシュ値配列内のすべての異なる値のカウントでハッシュを作成します。最初のステップでは、各要素に正しい数のゼロが含まれるようにハッシュを初期化し、2 番目のステップでは、データ内で検出された各値のカウントをインクリメントします。最後のループでは、結果の%countsハッシュの内容を出力します。

use strict;
use warnings;

my %data = (
  234 => [ qw/aa bb aa ab aa/ ],
  235 => [ qw/aa ab aa bb aa/ ],
  236 => [ qw/bb aa aa aa bb/ ],
);

my %counts;
$counts{$_} = [ (0) x @{(values %data)[0]} ] for map @$_, values %data;

for my $i ( 0 .. $#{(values %data)[0]} ) {
  $counts{$_}[$i]++ for map $_->[$i], values %data;
} 

while (my ($k, $v) = each %counts) {
    printf "%s => (%s)\n", $k, join ', ', @$v;
}

出力

ab => (0, 1, 0, 1, 0)
bb => (1, 1, 0, 1, 1)
aa => (2, 1, 3, 1, 2)
于 2012-07-29T05:31:35.183 に答える
0
use Data::Dumper;

%hash = (234 => [aa, bb, aa, ab, aa],
         235 => [aa, ab, aa, bb, aa],
         236 => [bb, aa, aa, aa, bb],
        );

do { $i = 0; $element{$i++}->{$_}++ for @{$_}; } for (values %hash);

print Dumper(\%element);
于 2012-07-29T02:58:26.363 に答える
0

これは、より perl っぽい (必ずしも優れているとは限りません) 方法です。コードを保守している人が perl をよく知っていない限り、あまり明確ではありません。とはいえ、map と grep について学ぶことは悪い考えではありません。それらに慣れると、コードの意図をより明確にするのに役立ちます。各ソリューションを調べて、それぞれがどのように機能するかを理解しようとすることをお勧めします。

このソリューションは、短すぎる配列を処理しますが、アプリケーションによっては、これが探しているものである場合とそうでない場合があります。

use warnings;
use strict;

use Data::Dumper;

my %hash = (
    '234' => [qw(aa bb aa ab aa)],
    '235' => [qw(aa ab aa bb aa)],
    '236' => [qw(bb aa aa aa bb)],
);

my @result = ();

while ( grep {scalar @{$_}} values %hash ) {
    push @result, scalar @{[
        grep {$_ eq 'bb'}
            map {shift @{$_}}
                values %hash
    ]};
}

print Dumper \@result;
于 2012-07-29T04:43:28.140 に答える