2012-09-21 40 views
14

Tôi khá mới đối với Perl, vì vậy hãy tha thứ cho tôi nếu điều này có vẻ như một câu hỏi đơn giản ...Perl Làm thế nào để lấy một mảng từ một mảng băm?

Dù sao, tôi có một mảng băm và tôi đang cố truy xuất một trong các mảng trong băm, nhưng tất cả những gì tôi có thể nhận được là kích thước vô hướng của mảng.

%HoA = a hash of arrays 
$key = some key in the hash 

foreach $nextItem (@HoA{$key}) { 
    do a bunch of stuff with $nextItem 
} 

Khi tôi làm điều này, $ nextItem luôn là kích thước của mảng và vòng lặp chỉ chạy qua một lần. Tôi đã thử in các nội dung sau:

@HoA{$key} 
$HoA{$key} 
@$HoA{$key} 

Hai chữ đầu tiên cho tôi kích thước vô hướng và thứ ba cho tôi không có gì ... tôi thiếu gì ở đây?

CẬP NHẬT: Tôi tự hỏi nếu vấn đề của tôi thực sự là cách tôi thêm mảng vào băm. Dưới đây là những gì tôi đang làm:

@HoA{$key} = split(/ /, $list); 

Điều đó có gắn mảng trong giá trị băm hoặc mảng trong giá trị băm không?

UPDATE 2: Tôi đã thử các khối mã sau đây:

my $key = "TEST"; 
my %HoA =(); 
my @testarray = (1, 2, 3); 
@HoA{$key} = @testarray; 
print Dumper(%HoA); 

Dưới đây là kết quả:

$VAR1 = 'TEST'; 
$VAR2 = 1; 

Tại sao nó chỉ bám giá trị đầu tiên của mảng trong?

Trả lời

13

Hãy thử tham khảo mảng của bạn theo cách này:

%HoA = a hash of arrays 
$key = some key in the hash 

foreach $nextItem (@{$HoA{$key}}) { 
    do a bunch of stuff with $nextItem 
} 

Bạn lấy tham chiếu mảng tại $HoA{$key} và làm cho nó một mảng.

Edit: Đối với bản cập nhật của bạn, tôi nghĩ rằng bạn sẽ có được những gì bạn muốn, nếu bạn làm điều đó theo cách này:

@{$HoA{$key}} = split(/ /, $list); 

hoặc bạn có thể làm

push(@{$HoA{$key}}, split(/ /, $list); 

Ví dụ:

my $list = "fred joe brown sam"; 
my %HoA =(); 
my $key = "jacob"; 
@{$HoA{$key} = split(/ /, $list); 
foreach my $item (@{$HoA{$key}}) 
{ 
    print "Test item: $nextItem\n"; 
} 

You will get: 
Test item: fred 
Test item: joe 
Test item: brown 
Test item: sam 

Chỉnh sửa: Thêm use strict; vào đầu chương trình của bạn. Về cơ bản bạn đang cố gắng sử dụng HoA như một mảng khi bạn có một băm được xác định. Bạn đang tham khảo nội dung của hàm băm của bạn không đúng cách. Để làm điều đó đúng, bạn thực sự thực sự cần phải có một số $ giữa @HoA. Perl là không có chữ và sẽ cho phép bạn thoát khỏi vụ giết người nếu bạn không use strict;. A reference excerpt from oreilly có thể xóa một số thứ.

my @testarray là một mảng
my %hash là một hash
$hash{$el1} = \@array là một yếu tố băm có giá trị của một ref để một mảng
@{$hash{$el1}} = @array là một yếu tố băm có chứa một mảng

+0

Tôi cố gắng đó . Nó chỉ trả về một kích thước bằng không và vòng lặp thậm chí không thực hiện một lần. – mrplainswalker

+0

@mrplainswalker - Thử in ra nội dung của băm và đảm bảo nó có cấu trúc mà bạn nghĩ nó có. Có lẽ bạn chính là không xác định hoặc không phải là một mảng như bạn nghĩ. Bạn có thể sử dụng Data :: Dumper; Dumper (% HoA) để kiểm tra.Bạn cũng có thể thực hiện nếu (được định nghĩa ($ HoA {$ key})) {print "Defined"} như một bài kiểm tra nhanh – scrappedcola

+0

Ok, tôi đã thử hàm Dumper để xem nội dung trong băm và bạn nói đúng. .. nó không phải là những gì tôi mong đợi. Mỗi giá trị chỉ là mục đầu tiên trong mảng chứ không phải toàn bộ mảng. – mrplainswalker

2
@array 

Cách bạn nhận được mảng, do đó,

@{ $array_ref } 

tương đương với tham chiếu mảng.

$HoA{$key} 

là một tham chiếu đến một mảng, vì vậy

@{ $HoA{$key} } 

là mảng đó.

for my $nextItem (@{ $HoA{$key} }) 
6

Mỗi mục trong băm của bạn là một tài liệu tham khảo vào một mảng. Ví dụ:

$my_hash{$key} 

là một tài liệu tham khảo để một mảng và không phải là một mảng. $my_hash{$key} chỉ trỏ đến một vùng trong bộ nhớ mà mảng đó tồn tại. Để dereference nó, bạn đặt các biểu tượng mảng trước:

@{ my_hash{$key} } 

Những điều nhận được một chút hairier khi chúng tôi bắt đầu nói về các yếu tố:

${ my_hash{$key} }[0] 

là yếu tố đầu tiên của mảng đó. Bạn có thể tưởng tượng nếu mảng đó bao gồm các băm cho các mảng khác, cú pháp có thể trở nên khá khó hiểu. May mắn thay, Perl có cách xử lý sạch sẽ:

$my_hash{$key}->[0]; 

Điều đó hoàn toàn giống như trên, nhưng dễ hiểu hơn về cú pháp. Đôi khi, nó dễ dàng hơn để sử dụng các biến trung gian chỉ để bạn có thể tham khảo những thứ mà không cần tất cả các dereferencing:

my %hash_of_array_refs; 

foreach my $key (sort keys %hash_of_array_refs) { 
    my @array = @{ $hash_of_array_refs{$key} }; #Dereference 
    foreach my $element (@array) {     #Much easier to read and understand 
     say "First element is $array[0]"; 
     say "last element is $array[$#array]"; 
     say "This element: $element"; 
    } 
} 

Without dereferencing bạn có được điều này:

my %hash_of_array_refs; 

foreach my $key (sort keys %hash_of_array_refs) { 
    foreach my $element (@{ $hash_of_array_refs{$key} }) {     #Much easier to read and understand 
     say "First element is " . $hash_of_array_refs->[0]; 
     say "last element is " . $hash_of_array_refs->[$#{ $hash_of_array_refs{key} } ]"; 
     say "This element: $element"; 
    } 
} 
+0

+1 ~ CẢM ƠN BẠN !! Tôi đã xem xét một số bài báo và BẠN là người đầu tiên giải thích cách truy cập một phần tử bên trong một mảng băm của mảng bằng cách sử dụng $ myhash {$ key} -> [0]. –

0

"Tại sao nó chỉ bám giá trị đầu tiên của mảng trong? "

Bạn cần phải đặt một tham chiếu đến mảng của bạn vào băm bằng cách đặt trước nó với một dấu chéo ngược:

$HoA{$key} = \@testarray; 

Sau đó, khi bạn lấy nó từ băm bạn dereference:

@testarray = @{ $HoA{$key} }; 
+0

Đúng, nhưng điều này đã không được chỉ ra trong các câu trả lời khác? Tôi không rõ câu trả lời của bạn bổ sung ở đây. –

+0

Các câu trả lời khác giả định rằng ông đã có tài liệu tham khảo trong băm và không giải quyết vấn đề cố gắng để đặt một mảng trong một băm mà không tham chiếu. Các câu trả lời khác đã được chỉnh sửa. – RobEarl

Các vấn đề liên quan