0

最初に、このような質問をされたことをお詫び申し上げます。ハッシュ参照の配列を数える方法を見つけなければ、答えを探すのは難しい

私の関数は、電子メール アドレスを含むハッシュ参照の配列である DBI クエリからの出力を受け取ります。タスクは、ドメイン名ごとに電子メール アドレスの毎日の数を保持することです。私がしているのは、カウントするドメインのハッシュを構築することです。ポイントは、アレイが少なくとも 10,000,000 通の電子メールを格納することが期待されていることです。スクリプトの実行には数分かかりました。

問題は、アルゴリズムを単純化する方法を思いつくことができるかということです。

my ($data) = shift;
my %elements = ( );

foreach my $row (@$data)
{
    my ($username, $domain) = split(/@/, $row->{addr});
    if (exists($elements{$domain}))
    {
        $elements{$domain}++;
    }
    else
    {
        $elements{$domain} = 1;
    }

}

ところで、私の英語は申し訳ありませんが、私はネイティブ スピーカーではありません。ありがとう。

4

3 に答える 3

1

文字列に が 1 つしか含まれていない場合に実行できる最適化が 1 つあります@

(split /\@/, $string)[1]

と同等ですが、効率は劣ります

substr $string, 1 + index $string, '@'

その行があまり頻繁に実行されない場合、パフォーマンスの向上はそれほど劇的ではありませんが、実行したばかりの非常に非科学的なベンチマークでは、実行時間が半分になりました.

もう 1 つの違いは、no@が存在する場合の動作です。split解決策ではundef、空の文字列に文字列化される が返されますが、index解決策では最後の文字が返されます。

@ハッシュキーの先頭が気にならない場合は、効率をさらに高めることができます。

substr $string, index $string, '@'
于 2013-02-12T18:21:15.817 に答える
1

if/else ロジックは必要ありません。Perl は、まだハッシュに含まれていないキー (この場合はドメイン) のカウントを初めてインクリメントしようとすると、カウントを 1 に設定するほどスマートです。

if をなくし、インクリメントを維持します。効率が大幅に向上することはないでしょうが、少しは向上します。そうしないと、ループが非常にタイトになります。

于 2013-02-12T16:53:39.490 に答える
0

あなたのアルゴリズムはすでに O(N) であり、これはカウンティング アルゴリズムと同じくらい効率的です。句を削除するなどのマイクロ最適化を行うことはできifますが、アルゴリズムの改善は得られません。

于 2013-02-12T18:21:51.653 に答える