2

各キーに 3 つの異なる値がある状況があります。次のようにデータを印刷する必要があります。

K1 V1 V2 V3
K2 V1 V2 V3
…
Kn V1 V2 V3

以下にリストされている以外に、これを達成するための効率的で簡単な代替方法はありますか? 私は2つのアプローチを考えています:

  1. 各キーの 3 つの異なる値に対して 3 つのハッシュを維持します。キーに基づいて 1 つのハッシュを反復処理し、他の 2 つのハッシュから値を取得して出力します。

    ハッシュ 1 - K1->V1 ...
    ハッシュ 2 - K1->V2 ...
    ハッシュ 3 - K1->V3 ...
  2. 値の配列を参照するためのキーを持つ単一のハッシュを維持します。ここでは、1 つのハッシュのみを繰り返して読み取る必要があります。

    K1 --> Ref{V1,V2,V3}

EDIT1:

主な課題は、値 V1、V2、V3 が異なる場所で導出され、配列として一緒にプッシュできないことです。したがって、ハッシュ値を配列への参照として作成すると、次の値を追加するたびに逆参照する必要があります。

たとえば、私は subroutine1 にいます - 私は Hash1 にデータを取り込みました -K1-->[V1] 私は subroutine2 にいます - 私は de-reference してから[V1]push する必要がありV2ます。したがって、ハッシュは になりK1-->[V1 V2]V3別のルーチンに追加されます。K1-->[V1 V2 V3]

EDIT2:

今、私は別の課題に直面しています。に基づいてハッシュをソートする必要がありV3ます。キーとリストの参照を使用してハッシュを保存することはまだ可能ですか?

K1-->[V1 V2 V3]

4

5 に答える 5

9

オプション1が何にとっても便利だとは想像できませんが、データで何をしたいかによって異なります。

インデックス 0、1、2 を使用して , を参照することに満足している場合、またはそれらの値を個別に処理したくない場合は、V1配列のハッシュを使用します。V2V3

my %data;
$data{K1}[0] = V1;
$data{K1}[1] = V2;
$data{K1}[2] = V3;

または、もちろん

$data{K1} = [V1, V2, V3];

追加のオプションとして、値が名前付け可能なものを意味する場合は、ハッシュのハッシュを使用できます。

my %data;
$data{K1}{name} = V1;
$data{K1}{age} = V2;
$data{K1}{height} = V3;

また

$data{K1}{qw/ name age height /} = (V1, V2, V3);

最後に、個々の値にアクセスする必要がない場合は、次のようにファイルにそのまま残しても問題ありません。

my %data;
$data{K1} = "V1 V2 V3";

しかし、私が言ったように、内部ストレージは主にデータへのアクセス方法に依存しており、あなたはそれについて教えてくれませんでした.


編集

あなたが言う今

主な課題は、値 V1、V2、V3 が異なる場所で導出され、配列として一緒にプッシュできないことです。

おそらくハッシュのハッシュの方が適切だと思いますが、実行時間に関しては取るに足らない操作であるため、逆参照についてはまったく心配しません。ただしpush、正しい順序でデータを追加する必要があるため、使用しません。

どちらを好むかに応じて、次の選択肢があります

$data{K1}[2] = V3;

また

$data{K1}{height} = V3;

明らかに後者の方が読みやすいです。


編集 2

要求に応じて、ハッシュのハッシュを 3 番目の値 (height私の例では) でソートするには、次のように記述します。

use strict;
use warnings;

my %data = (
  K1 => { name => 'ABC', age => 99, height => 64 },
  K2 => { name => 'DEF', age => 12, height => 32 },
  K3 => { name => 'GHI', age => 56, height => 9 },
);

for (sort { $data{$a}{height} <=> $data{$b}{height} } keys %data) {
  printf "%s => %s %s %s\n", $_, @{$data{$_}}{qw/ name age height / };
}

または、データが配列のハッシュとして格納されている場合

use strict;
use warnings;

my %data = (
  K1 => [ 'ABC', 99, 64 ],
  K2 => [ 'DEF', 12, 32 ],
  K3 => [ 'GHI', 56, 9 ],
);

for (sort { $data{$a}[2] <=> $data{$b}[2] } keys %data) {
  printf "%s => %s %s %s\n", $_, @{$data{$_}};
}

両方のスクリプトの出力は同じです

K3 => GHI 56 9
K2 => DEF 12 32
K1 => ABC 99 64
于 2012-04-23T17:23:29.293 に答える
1

読みやすさ/保守性の点では、2 番目の方が優れているようです。最初の危険性は、1 つのハッシュに存在するキーが他のハッシュに存在しないことになる可能性があることです。また、最初のアプローチに出くわした場合、しばらく考えなければなりませんが、最初のアプローチは「自然」(またはより一般的なイディオム、より実用的なもの、またはそれを理解することを意味する何か)のようですより容易に)。

于 2012-04-23T16:51:10.547 に答える
1

2 番目のアプローチ (キーごとに 1 つの配列参照) は次のとおりです。

  1. 私の経験では、はるかに一般的ですが、
  2. データ構造が 3 つではなく 1 つしかないため、維持が簡単です。
  3. DRY の原則とより一致しています。「すべての知識は、システム内で単一の、明確で、信頼できる表現を持っている必要があります。」キーを 3 回ではなく 1 回表現します。
于 2012-04-23T16:48:20.803 に答える
0

選択は、使用パターンに大きく依存します。具体的には、手続き型プログラムとオブジェクト指向プログラミングのどちらを使用するかによって異なります。

これは哲学的な違いであり、言語レベルのクラスとオブジェクトが使用されているかどうかとは関係ありません。手続き型プログラミングは、ワークフローを中心に編成されています。プロシージャは、必要なデータにアクセスして変換します。OOP はデータのレコードを中心に編成されています。メソッドは、特定の 1 つのレコードのみにアクセスして変換します。

2 番目のアプローチは、オブジェクト指向プログラミングと密接に連携しています。オブジェクト指向プログラミングは、Perl で群を抜いて最も一般的なプログラミング スタイルであるため、最近では (より多くのメモリを必要としますが) 2 番目のアプローチが一般的に好まれる構造になっています。

しかし、あなたの編集は、より手続き的なアプローチを使用している可能性があることを暗示しています. お気づきのように、手続き型プログラミングには最初のアプローチの方が便利です。これは、手続き型プログラミングが流行したときに非常に一般的に使用されました。

コードの構成に最も適したものを選択してください。

于 2012-04-23T17:38:59.770 に答える
0

確かに、データ構造を 1 つだけ保持する方がよいでしょう。

%data = ( K1=>[V1, V2, V3], ... );

Data::Dumpを使用して、データ構造をすばやく表示/デバッグできます。

于 2012-04-23T16:48:29.217 に答える