2011-10-04 31 views
4

問題是我有一個數組,它具有鍵值對作爲數組中的元素,我必須將它們分解成哈希中的key =>值對。如何將數組[key1,val1]映射到perl中的散列{key1 => val1}?

我在第一次嘗試的作品,但我認爲它相當混亂 - 我得陣列的所有其他元素,然後篩選通過找到接受鍵創建哈希與

my $HASH; 
my $ARRAY = [ key1, val1, key2, val2, __key3__, val3, __key4__, val4 ]; 
    my @keys = map{ $ARRAY[ $_*2 ] } 0 .. int($#ARRAY/2); 
    my @vals = map{ $ARRAY[ $_*2+1 ] } 0 .. int($#ARRAY/2); 

    my $i = 0; 
    #filter for keys that only have __key__ format 
    for $key (@keys){ 
     if($key && $key =~ m/^__(.*)__$/i){ 
     $HASH{$1} = $vals[$i]; 
     } 
    $i++; 
    } 
    # only key3 and key4 should be in $HASH now 

我發現這個sample code我認爲這是接近我正在尋找,但我無法弄清楚如何實現一個數組類似的東西,而不是在一個文本文件的行迭代:

$file = 'myfile.txt' 
open I, '<', $file 
my %hash; 
%hash = map { split /\s*,\s*,/,$_,2 } grep (!/^$/,<I>); 
print STDERR "[ITEM] $_ => $hash{$_}\n" for keys %hash; 

可以在任何的你perl guru在那裏幫助我理解做到這一點的最佳方式?即使我可以以某種方式將所有元素加入到一個字符串中,然後再將每個第二個空白符號分開 - 這也可能起作用,但是現在我被卡住了!

+0

'$ ARRAY = [...]'和'$ ARRAY [...]'是指兩個不同的變量! – mob

+1

@nodebunny =>添加'使用警告;嚴格使用;'放在所有程序的頂部,以捕捉像上面那個'mob'筆記這樣的問題。 –

+0

謝謝我使用麋,所以它已經在那裏! – qodeninja

回答

12

這是很容易的:

use strict; use warnings; 
use YAML; 

my $ARRAY = [qw(key1 val1 key2 val2 __key3__ val3 __key4__ val4)]; 
my $HASH = { @$ARRAY }; 

print Dump $HASH; 

輸出:

C:\Temp> 
--- 
__key3__: val3 
__key4__: val4 
key1: val1 
key2: val2
+0

哦,哇,不知道你可以轉儲數組,哈希會想出來。棒極了! – qodeninja

+0

+1第一個答案 – qodeninja

+1

@nodebunny:其實,我回答的時間戳是35秒前。 –

7
my $ARRAY = [ qw(key1 val1 key2 val2 key3 val3 key4 val4) ]; 
my $HASH = { @$ARRAY }; 
4

在你找到的示例代碼中,<I>部分在整個文件中讀取並返回一個列表的grep。 grep處理列表,然後將其傳遞給地圖。然後地圖創建自己的列表,這個列表被分配給散列。

當您將一個列表分配給一個散列時,該列表被假定爲一個鍵/值對的偶數列表。

這個列表來自哪裏並不重要,它可能是map,grep或split命令的輸出。它可以來自一個文件,它可以存儲在一個數組中。

你行:

my $HASH =(); 

沒有做什麼有用的東西。寫作my $HASH;是完全一樣的。

此時,$HASH未定義。當你有一個未定義的值,並將其解引用爲散列值%$HASH時,未定義的值將成爲散列值。

您可以更加明確,通過寫

my $HASH = {}; # note the curly braces and not parens 

如果你有鍵值對的數組列表:

%$HASH = @array; 

如果你有鑰匙的列表,列表值:

@$HASH{@keys} = @values; 

根據你的問題,這裏是一個簡單的方法來創建你的哈希從數組中過濾值:

my $HASH = {}; 
my $ARRAY = [ qw(key1 val1 key2 val2 __key3__ val3 __key4__ val4) ]; 

{my @list = @$ARRAY; # make a copy since splice eats the list 
    while (my ($k, $v) = splice @list, 0, 2) { 
     if ($k =~ /^__(.+)__$/) { 
      $$HASH{$1} = $v 
     } 
    } 
} 

use Data::Dumper; 

print Dumper($HASH); 

它打印:

$VAR1 = { 
      'key4' => 'val4', 
      'key3' => 'val3' 
     }; 

如果你想這樣做,所有在一行中,你可以使用函數mapn從我模塊List::Gen這就好比map功能,但它允許您可以隨意移動任何步長,而不是一次一個項目。

use List::Gen 'mapn'; 

%$HASH = mapn {/^__(.+)__$/ ? ($1, $_[1]) :()} 2 => @$ARRAY; 
+0

謝謝你。問題是我有一個鍵和值的列表 - 所有在同一個數組,並希望從他們創建一個哈希 - – qodeninja

+0

@nodebunny =>讓我知道如果我剛剛提出的更新涵蓋了你在找什麼。 –

+0

我想弄清楚如何獲得示例代碼,我必須使用數組而不是文件行 - 它看起來幾乎是正確的 – qodeninja

1

由於您的具體情況已經得到解答,我以爲我會回答您提出問題的問題。我期望看到的對陣列[ key => $value ],那你想投入或者散列的數組或哈希:

這個答案去像這樣:

my %hash = map { @$_ } [[ key1 => $value1 ], [ key2 => $value2 ], ... ]; 
my @ha = map {; { @$_ } } [[ key1 => $value1 ], [ key2 => $value2 ], ... ]; 

my %hash = @$array_ref_of_values; 

只是,我走每一個都通過解引用(@$_)來「爆炸」它們。

3
我不知道你可以轉儲數組,散列會想出來。

對於來自數組的值沒有什麼不可思議的。哈希沒有什麼可以弄清楚的。

如果您將列表分配給散列,它將清除散列,然後將列表視爲要從中初始化散列的鍵值對的列表。所以

%hash = (foo => 1, bar => 2); 

相當於

my @anon = (foo => 1, bar => 2); 
%hash =(); 
while (@anon) { 
    my $key = shift(@anon); 
    my $val = shift(@anon); 
    $hash{$key} = $val; 
} 

列表是一個列表。如果它是使用利用qw()

qw(x foo y bar) 

或使用陣列

@array 

因此,這意味着該列表/逗號運算

x => "foo", y => "bar" 

產生不要緊以下是所有的相同。

%hash = (x => "foo", y => "bar"); 
%hash = qw(x foo y bar); 
%hash = @array; # Assuming @array contains the correct values. 

,於是就有

$hash = { x => "foo", y => "bar" }; 
$hash = {qw(x foo y bar)}; 
$hash = { @array }; # Assuming @array contains the correct values. 
+0

確定關於=>的部分是否與之相同,以及沒有特別清楚的部分!謝謝@ikegami – qodeninja

+0

@nodebunny,差不多。 '=>'是''的一個奇特版本,可以自動引用剛纔出現的裸字(如果有的話)。 – ikegami

相關問題