Perlに完全で連続した整数マッピングを含むハッシュがある場合(つまり、0からnまでのすべてのキーが何かにマップされ、これ以外のキーはない)、これを配列に変換する方法はありますか?
キーと値のペアを反復処理して新しい配列に配置できることはわかっていますが、これを行うための組み込みの方法があるはずだということがわかります。
元のデータソースがハッシュの場合:
# first find the max key value, if you don't already know it:
use List::Util 'max';
my $maxkey = max keys %hash;
# get all the values, in order
my @array = @hash{0 .. $maxkey};
または、元のデータソースがハッシュリファレンスの場合:
my $maxkey = max keys %$hashref;
my @array = @{$hashref}{0 .. $maxkey};
これは、この例を使用して簡単にテストできます。
my %hash;
@hash{0 .. 9} = ('a' .. 'j');
# insert code from above, and then print the result...
use Data::Dumper;
print Dumper(\%hash);
print Dumper(\@array);
$VAR1 = {
'6' => 'g',
'3' => 'd',
'7' => 'h',
'9' => 'j',
'2' => 'c',
'8' => 'i',
'1' => 'b',
'4' => 'e',
'0' => 'a',
'5' => 'f'
};
$VAR1 = [
'a',
'b',
'c',
'd',
'e',
'f',
'g',
'h',
'i',
'j'
];
わかりました、これはあまり「組み込み」ではありませんが、機能します。また、「ソート」を含むすべてのソリューションよりも高速であるため、IMHOが優先されます。
map { $array[$_] = $hash{$_} } keys %hash; # Or use foreach instead of map
そうでなければ、効率が低下します:
my @array = map { $hash{$_} } sort { $a<=>$b } keys %hash;
Perlは、問題を解決するための組み込み機能を提供していません。
キーが特定の範囲をカバーしていることがわかっている場合0..N
、その事実を活用できます。
my $n = keys(%hash) - 1;
my @keys_and_values = map { $_ => $hash{$_} } 0 .. $n;
my @just_values = @hash{0 .. $n};
これにより、%hashed_keys
で定義されていないキーがundef
として残ります。
# if we're being nitpicky about when and how much memory
# is allocated for the array (for run-time optimization):
my @keys_arr = (undef) x scalar %hashed_keys;
@keys_arr[(keys %hashed_keys)] =
@hashed_keys{(keys %hashed_keys)};
また、参照を使用している場合:
@{$keys_arr}[(keys %{$hashed_keys})] =
@{$hashed_keys}{(keys %{$hashed_keys})};
または、もっと危険なことに、あなたが言ったことが真実であると想定しているため(常に真実であるとは限らないかもしれません...ただ言うだけです!):
@keys_arr = @hashed_keys{(sort {$a <=> $b} keys %hashed_keys)};
しかし、これは要点のようなものです。そもそもそれらが整数で索引付けされていたのなら、なぜ今はハッシュ化されているのですか?
$Hash_value =
{
'54' => 'abc',
'55' => 'def',
'56' => 'test',
};
while (my ($key,$value) = each %{$Hash_value})
{
print "\n $key > $value";
}
@a = @h{sort { $a <=> $b } keys %h};
以下のようにしばらく書くことができます:
$j =0;
while(($a1,$b1)=each(%hash1)){
$arr[$j][0] = $a1;
($arr[$j][1],$arr[$j][2],$arr[$j][3],$arr[$j][4],$arr[$j][5],$arr[$j][6]) = values($b1);
$j++;
}
$ a1にはキーが含まれ、$ b1には値が含まれます。上の例では、配列のハッシュがあり、配列には6つの要素が含まれています。
DVKが言ったように、組み込みの方法はありませんが、これでうまくいきます。
my @array = map {$hash{$_}} sort {$a <=> $b} keys %hash;
またはこれ:
my @array;
keys %hash;
while (my ($k, $v) = each %hash) {
$array[$k] = $v
}
どちらが速いかを確認するためのベンチマーク、私の推測は2番目でしょう。
簡単な方法は、@array = %hash
例えば、
my %hash = (
"0" => "zero",
"1" => "one",
"2" => "two",
"3" => "three",
"4" => "four",
"5" => "five",
"6" => "six",
"7" => "seven",
"8" => "eight",
"9" => "nine",
"10" => "ten",
);
my @array = %hash;
print "@array";
は次の出力を生成します。
3 3 9 9 5 5 8 8 2 2 4 4 1 1 10 10 7 7 0 0 6 6
[〜#〜] fm [〜#〜] の回答と Ether の回答を組み合わせると、本来は不要なスカラーを定義する必要がなくなります。
my @array = @hash{ 0 .. $#{[ keys %hash ]} };
きちんとしたことは、 scalar
アプローチとは異なり、$#
は、最初の要素のデフォルトインデックス $[
、ゼロ以外。
もちろん、それは愚かで難読化された何かを書くことを意味します:
my @array = @hash{ $[ .. $#{[ keys %hash ]} }; # Not recommended
しかし、その後は常にリモートチャンスがどこかでそれを必要とする(wince ))...