2014-06-20 36 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,所以语法可能是遥远,但要点是你要放置生成到值一个数组,然后将其全部包装在一个数组中