user3758693
user3758693

Reputation: 11

Transforming CSV data into a hash using Perl

I'm new to Perl. I'm trying to create a hash from a CSV file.

My CSV data currently looks like this:

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

I'd like the hash to look like this

$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 ],
                 },
              ]
           };

But I'm getting this instead

$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',
               }

        };

Here's the code I'm using so far. My CSV is in the output.csv file and I'm printing the hash in the hashr.txt file

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;

Upvotes: 1

Views: 414

Answers (2)

Miller
Miller

Reputation: 35198

Your desired data structure is strange, but the following should get you closer to what you say you want.

You probably could use a refresher of perldsc to learn more about Complex Data Structures.

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

Outputs:

[
  { 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"] },
]

Upvotes: 1

Rachael
Rachael

Reputation: 424

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 );

It's been years since I've touched perl, so that syntax is probably way off but the gist is you'll want to place the values generated into an array, then wrap it all in an array

Upvotes: 0

Related Questions