2014-06-20 35 views
1

我是Perl的新手。我正在嘗試從CSV文件創建一個哈希。使用Perl將CSV數據轉換爲哈希

我的CSV數據目前看起來是這樣的:

id,name,title,rating 
123,Andrew,Book 1,3 
1221,Abraham,Book 2,4 
43,Annie,Book 3,1 

我想哈希看起來像這樣

$reviews = { 
    review => [ 
       { 
        id  => [ 123 ], 
        name => [ Andrew ], 
        title => [ "Book 1" ], 
        rating => [ 3 ], 
       }, 
       { 
        id  => [ 1221 ], 
        name => [ Abraham ], 
        title => [ "Book 2" ], 
        rating => [ 4 ]] 
       }, 
       { 
        id  => [ 43 ], 
        name => [ Annie ], 
        title => [ "Book 3" ], 
        edition => [ 1 ], 
       }, 
       ] 
      }; 

但我發現了這個代替

$VAR1 = { 
    '123' => { 
        'name' => 'Andrew', 
        'title' => 'Book 1', 
        'id' => '123', 
        'rating' => '3', 
       }, 
    '1221' => { 
        'name' => 'Abraham', 
        'title' => 'Book 2', 
        'id' => '1221', 
        'rating' => '4', 
       }, 
    '43' => { 
        'name' => 'Annie', 
        'title' => 'Book 3', 
        'id' => '43', 
        'rating' => '1', 
       } 

     }; 

這是我目前使用的代碼。我的CSV是在output.csv文件,我打印的hashr.txt文件

my %hash; 
open (RESULTS, "output.csv")|| die "Can't open output.csv: $!\n"; 
open (HASHR, "+>hashr.txt")|| die "Can't open hashr.txt: $!\n"; 

while (<RESULTS>) { 
    last if /id/ 
} 
my $labels = $_; #save last line to label keys 
chop $labels; 

while (<RESULTS>) { 
    chomp; 
    my @array = split /,/; 
    my $index = 0; 
    my %h = map { $_ => $array[$index++]} split(",", $labels); 

    #my $key = "review"; 
    #$hash{$key}=\%h; 

    $hash{ $array[0] } = \%h; 
} 

print Dumper(\%hash); 
print HASHR Dumper(\%hash); 
close RESULTS; 
+1

您是否正在尋找真正屬於'[]'的值,它是perl中的一個匿名數組? – salparadise

+0

我認爲你已經比你想要的設計更好。你知道'$ reviews'是一個單元哈希,而且你的哈希值是單元數組嗎?因此,要訪問第二個評論的'name'字段,您必須編寫'$ reviews - > {review} [1] {name} [0]'。除非你需要在同一個結構中存儲更多的數據,否則如果'$ reviews'是一個數組引用,並且你的散列值是純字符串,會不會更好?這樣,訪問相同的項目看起來就像'$ reviews - > [1] {name}'這樣簡單得多,不易出錯。 – Borodin

回答

1

你想要的數據結構是奇怪的哈希,但下面應該讓你更接近你說你想要的。

您可能可以使用perldsc的進修來了解有關複雜數據結構的更多信息。

use strict; 
use warnings; 

my $header = <DATA>; 
chomp $header; 
my @headers = split /,/, $header; 

my @records; 
while (<DATA>) { 
    chomp; 
    my @cols = split /,/; 
    my %hash; 
    @hash{@headers} = map [$_], @cols; 
    push @records, \%hash; 
} 

use Data::Dump; 
dd \@records; 

__DATA__ 
id,name,title,rating 
123,Andrew,Book 1,3 
1221,Abraham,Book 2,4 
43,Annie,Book 3,1 

輸出:

[ 
    { id => [123], name => ["Andrew"], rating => [3], title => ["Book 1"] }, 
    { id => [1221], name => ["Abraham"], rating => [4], title => ["Book 2"] }, 
    { id => [43], name => ["Annie"], rating => [1], title => ["Book 3"] }, 
] 
+0

@Borodin我意識到我可能不應該這樣做,但我有時會調整我的編碼風格偏好只是爲了迎合語法熒光筆。我可能最常用正則表達式來做這些事情,當語法突出顯示器像在上面用'//'分裂的時候,在其後的分割中沒有跟上時,更強烈地傾向於'{} {'和'///''}一個分號。無法贏得任何地方,我想:) – Miller

+0

我很同情,但Perl因其最佳猜測解析而臭名昭着,適當的熒光筆將不得不編譯代碼才能正確解析。這使得無法正確突出顯示任何不能編譯的東西。我會傾向於編寫最佳實踐代碼,並在必要時使用<! - language:lang-none - >'刪除突出顯示。畢竟,熒光筆在* __DATA__'中被綁定*以弄亂任何東西。在任何情況下,默認突出顯示都使用這種柔和的顏色,我通常會忽略它。 – Borodin

+0

是的,語法突出顯示很差,但它偶爾還會出現錯誤。事情是,有更好的解析器,就像我的編輯Sublime Text使用的解析器。幾乎讓我想爲['Google Prettifier'](http://google-code-prettify.googlecode.com/svn/trunk/README.html)做出貢獻,但現在不太可能在這裏投入時間:) – Miller

0
review => [ 
      { 
       id  => [ 123 ], 
       name => [ Andrew ], 
       title => [ "Book 1" ], 
       rating => [ 3 ], 
      }, 

'123' => { 
       'name' => 'Andrew', 
       'title' => 'Book 1', 
       'id' => '123', 
       'rating' => '3', 
      }, 


my %h = map { $_ => $array[$index++]} split(",", $labels); 


to 

my %h = map { $_ => @{$array[$index++]}} split(",", $labels); 

它已經多年,因爲我已經感動的Perl,所以語法可能是遙遠,但要點是你要放置生成到值一個數組,然後將其全部包裝在一個數組中