22

次のプログラムでハッシュを使用して出現をカウントした後、実際のリストの順序を維持するにはどうすればよいですか? たとえば<DATA>

a
b
e
a
c 
d 
a
c
d
b
etc.

ハッシュを使用して、各要素の出現をカウントしました。

そして私が欲しいのは:

a  3
b  2
e  1
c  2
d  2

しかし、次のプログラムはそうではないことを示しています。

my (%count, $line, @array_1, @array_2);
while ($line = <DATA>) {
    $count{$line}++ if ( $line =~ /\S/ );
}
@array_1 = keys(%count);
@array_2 = values(%count);
for(my $i=0; $i<$#array_1; $i++)
{
   print "$array_1[$i]\t $array_2[$i]";
}
4

7 に答える 7

36

ハッシュは順序付けされていませんが、いつものように、CPAN は解決策を提供します: Tie::IxHash

use Tie::IxHash;
my %count;
tie %count, 'Tie::IxHash';

while ($line = <DATA>) {
$count{$line}++ if ( $line =~ /\S/ );
}

while( my( $key, $value)= each %count) {
    print "$key\t $value"; 
}
于 2009-10-13T08:46:33.063 に答える
15

ハッシュテーブルのデータは、キーのハッシュコードの順序で格納されます。これは、ほとんどの場合、ランダムな順序のようなものです。また、各キーの最初の出現の順序を保存する必要があります。この問題に取り組む1つの方法は次のとおりです。

my (%count, $line, @display_order);
while ($line = <DATA>) {
    chomp $line;           # strip the \n off the end of $line
    if ($line =~ /\S/) {
        if ($count{$line}++ == 0) {
            # this is the first time we have seen the key "$line"
            push @display_order, $line;
        }
    }
}

# now @display_order holds the keys of %count, in the order of first appearance
foreach my $key (@display_order)
{
    print "$key\t $count{$key}\n";
}
于 2009-10-13T07:34:04.083 に答える
10

perlfaq4の回答から「要素を入れた順序をハッシュに記憶させるにはどうすればよいですか?


要素を入れた順序をハッシュに記憶させるにはどうすればよいですか?

CPANのTie::IxHashを使用します。

use Tie::IxHash;

tie my %myhash, 'Tie::IxHash';

for (my $i=0; $i<20; $i++) {
    $myhash{$i} = 2*$i;
    }

my @keys = keys %myhash;
# @keys = (0,1,2,3,...)
于 2009-10-13T13:26:06.017 に答える
6

単に:

my (%count, @order);
while(<DATA>) {
  chomp;
  push @order, $_ unless $count{$_}++;
}
print "$_ $count{$_}\n" for @order;
__DATA__
a
b
e
a
c
d
a
c
d
b

またはワンライナーとして

perl -nlE'$c{$_}++or$o[@o]=$_}{say"$_ $c{$_}"for@o'<<<$'a\nb\ne\na\nc\nd\na\nc\nd\nb'
于 2009-10-13T11:07:13.090 に答える
5

もう 1 つのオプションは、David Golden (@xdg) の単純で純粋な perlHash::Orderedモジュールです。ハッシュが舞台裏のオブジェクトになり、ハッシュ要素にアクセスして変更するためのメソッドを使用するため、順序は得られますが遅くなります。

モジュールが通常のハッシュよりもどれだけ遅いかを定量化できるベンチマークはおそらくありますが、小さなスクリプトでキー/値のデータ構造を操作するにはクールな方法であり、その種のアプリケーションでは十分に高速です。ドキュメントには、ハッシュを順序付けするための他のいくつかのアプローチについても言及されています。

于 2015-03-09T21:36:40.763 に答える
4

これが常に優れた手法であるとは確信していませんが、時々使用しました。「見られた」タイプのハッシュを持つだけでなく、カウントと通知された順序の両方を格納できます。

基本的に、$count{$line}見られた回数ではなく、見られた回数であり$count{$line}{count}、見られ$count{$line}{order}た順序です。

my %count;
while (my $line = <DATA>) {
    chomp $line;
    if ($line =~ /\S/) {
        $count{$line} ||= { order => scalar(keys(%count)) };
        $count{$line}{count}++;
    }
}

for my $line (sort { $count{$a}{order} <=> $count{$b}{order} } keys %count ) {
    print "$line $count{$line}{count}\n";
}
于 2015-03-09T20:25:22.517 に答える