【问题标题】:CSV into hashCSV 转换成哈希
【发布时间】:2010-11-04 03:26:59
【问题描述】:

我有一个 csv,第一列是一个标签,后跟逗号分隔值:

LabelA,45,56,78,90
LabelB,56,65,43,32
LabelC,56,87,98,45

我希望第一列(LabelA 等)成为散列中的键,其中包含数组中的数值。

我可以将文件读入数组或标量,但我不确定之后该怎么做。建议??

编辑: 好的,所以看起来这会将值分配给键..但是在我的示例中逗号分隔的数字呢?他们要去哪?他们在 %hash 中吗?如果是这样,您是否可以进一步降低您的解释?谢谢。

【问题讨论】:

  • depesz 正在创建一个数组哈希。尝试阅读我给你的 perldsc 链接。它是“Data Structures Cookbook”,其中有一节是关于使用数组散列的,我还在我的帖子中为你链接了该部分。 HoA 的生成部分有一个与您要求的非常相似的示例。

标签: perl hash


【解决方案1】:

请参阅 perlfunc splitperldsc

  1. 阅读每一行。
  2. 咬一口。
  3. 用逗号分隔。
  4. 使用结果中的第一个值作为 HoA 的键。
  5. 其他值成为数组。
  6. 将数组的引用存储在键下的哈希中。
  7. ...
  8. 利润!!!

创建一个hash of array references:

您的数据结构应如下所示:

my %foo = (
    LabelA => [  2, 3,  56, 78, 90 ],
    LabelB => [ 65, 45, 23, 34, 87 ],
    LabelC => [ 67, 34, 56, 67, 98 ],
);

【讨论】:

    【解决方案2】:

    好吧,我们假设没有特殊字符等等。

    首先打开文件:

    open my $fh, '<', 'some.file.csv' or die "Cannot open: $!";
    

    然后你循环读取它:

    while (my $line = <$fh>) {
    

    然后,您删除尾随的白色字符(\n 和其他字符):

    $line =~ s/\s*\z//;
    

    并将其拆分为数组:

    my @array = split /,/, $line;
    

    当它在数组中时,你会从数组中取出第一个元素:

    my $key = shift @array;
    

    并将其存储在哈希中:

    $hash{$key} = \@array;
    

    (\@array 表示对数组的引用)。

    完整代码:

    my %hash;
    open my $fh, '<', 'some.file.csv' or die "Cannot open: $!";
    while (my $line = <$fh>) {
      $line =~ s/\s*\z//;
      my @array = split /,/, $line;
      my $key = shift @array;
      $hash{$key} = \@array;
    }
    close $fh;
    

    【讨论】:

    • 好的,所以看起来这会将值分配给键..但是在我的示例中逗号分隔的数字呢?他们要去哪?他们在 %hash 中吗?如果是这样,您是否可以进一步降低您的解释?谢谢。
    • 好吧,这一行:$hash{$key} = \@array;将值放入哈希中。您可以添加:使用 Data::Dumper;打印转储器(\%hash);在程序结束时查看数据结构的外观。
    • 使用此方法的其他人请注意:输入 CSV 中的空白行将导致键/值对为 '' =&gt; undef。不是这种方法的错,这在这段代码的上下文中是有意义的,只是需要注意的事情,例如如果您使用的 Excel CSV 文件在行中有一些空白(空白行)。
    【解决方案3】:

    就个人而言,我喜欢Text::CSV_XSIO::File 模块:

    use Text::CSV_XS;
    use IO::File;
    
    # Usage example:
    my $hash_ref = csv_file_hashref('some_file.csv');
    
    foreach my $key (sort keys %{$hash_ref}){
       print qq{$key: };
       print join q{,}, @{$hash_ref->{$key}};
       print qq{\n};
    }
    
    # Implementation:
    sub csv_file_hashref {
       my ($filename) = @_;
    
       my $csv_fh = IO::File->new($filename, 'r');
       my $csv = Text::CSV_XS->new ();
    
       my %output_hash;
    
       while(my $colref = $csv->getline ($csv_fh))
       {
          $output_hash{shift @{$colref}} = $colref;
       }
    
       return \%output_hash;
    }
    

    【讨论】:

    • Text::CSV 是标准发行版的一部分。因此我选择使用它。只需从 USE 和构造函数中删除 _XS。
    【解决方案4】:

    Text::CSV::Hashify

    将 CSV 文件转换为 Perl 哈希:

    # Simple functional interface
    use Text::CSV::Hashify;
    $hash_ref = hashify('/path/to/file.csv', 'primary_key');
    
    # Object-oriented interface
    use Text::CSV::Hashify;
    $obj = Text::CSV::Hashify->new( {
            file        => '/path/to/file.csv',
            format      => 'hoh', # hash of hashes, which is default
            key         => 'id',  # needed except when format is 'aoh'
            max_rows    => 20,    # number of records to read; defaults to all
            ... # other key-value pairs possible for Text::CSV
    } );
    
    # all records requested
    $hash_ref       = $obj->all;
    

    【讨论】:

      【解决方案5】:

      我认为这也可以更轻松。

      $refhash 变量将是对哈希数组的引用。

      每个散列包含标题(作为散列键)和一个 CSV 行的值。 该数组包含 CSV 中所有行的哈希值。

      use Text::CSV_XS qw( csv );
      $refhashvariable = csv(
          in      => "$input_csv_filename",
          sep     => ';',
          headers => "auto"
      );    # as array of hash
      

      这对我有用。如果 CSV 没有标题,我没有尝试过。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-30
        • 2016-04-03
        • 2012-12-21
        • 1970-01-01
        • 2018-02-05
        • 2019-10-27
        • 2019-05-23
        • 1970-01-01
        相关资源
        最近更新 更多