【问题标题】:Transforming CSV data into a hash using Perl使用 Perl 将 CSV 数据转换为哈希
【发布时间】:2014-08-10 19:36:16
【问题描述】:

我是 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;

【问题讨论】:

  • 您是否正在寻找真正的值 [],它是 perl 中的匿名数组?
  • 我认为你已经拥有的比你想要的设计要好得多。您是否意识到$reviews 是一个单元素散列,而您的散列值是单元素数组?因此,要访问第二条评论的name 字段,您必须编写$reviews-&gt;{review}[1]{name}[0]。除非你有更多的数据需要存储在同一个结构中,否则如果$reviews 是一个数组引用并且你的哈希值是纯字符串不是更好吗?这样一来,访问同一个项目看起来就像$reviews-&gt;[1]{name},它更简单,更不容易出现错误。

标签: perl csv hash


【解决方案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"] },
]

【讨论】:

  • @Borodin 我意识到我可能不应该这样做,但有时我会为 SO 调整我的编码风格偏好,以迎合语法高亮。我可能最常使用正则表达式执行此操作,更倾向于s{}{} 而不是s///,当语法高亮器像上面使用// 那样在没有分号的拆分中搞砸事情时。我想不可能到处都赢:)
  • 我很同情,但 Perl 因其最佳猜测解析而臭名昭著,并且必须使用适当的荧光笔编译代码才能使其正确。这使得无法正确突出显示任何未编译的内容。我倾向于编写最佳实践代码,并在必要时使用&lt;!-- language: lang-none --&gt; 删除突出显示。毕竟,荧光笔绑定会弄乱__DATA__ 中的任何内容。无论如何,默认突出显示使用我通常忽略的柔和颜色
  • 是的,糟糕的语法高亮是非常轻微的,但它仍然偶尔会困扰我。问题是,有更好的解析器,比如我的编辑器 Sublime Text 使用的解析器。几乎让我想为Google Prettifier 做出贡献,但现在不太可能在那里投入时间:)
【解决方案2】:
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 以来已经有好几年了,所以这种语法可能已经过时了,但要点是您需要将生成的值放入一个数组中,然后将其全部包装在一个数组中

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-11-11
    • 2021-07-13
    • 1970-01-01
    • 1970-01-01
    • 2017-01-06
    • 2016-04-03
    • 2011-02-23
    • 2011-05-30
    相关资源
    最近更新 更多