AnnaSpanner has asked for the wisdom of the Perl Monks concerning the following question:

Please could some wonderfully compassionate Perl Monk please read this script and tell me what the problem is. I have explained what I am doing using comments in the script itself. See line final comment for the problem. I have two csv files, one of them, fruit.csv, contains apples,5 in the first row, and the other, fruit_names.csv, simply contains apples in the first row. I create a hash, %fruit, with a single key value pair, (apples 5), which are both read from fruit.csv. I then read "apples" from the first line of fruit_names.csv, and use this as the key to access the value from %fruit, hoping to get the value 5. But this DOES NOT WORK. Why is this?

my %fruit; # create hash open(FRUIT, "fruit.csv"); while(<FRUIT>){ @line = split (",", $_); $fruit_name = $line[0]; # the value of this is obviously apples $number = $line[1]; # the value of this is 5 $fruit{$fruit_name} = $number; # puts key-value pair (apples 5) into t +he hash } close(FRUIT); open(FRUITNAMES, "fruit_names.csv"); while(<FRUITNAMES>){ @line = split (",", $_); $thefruitsname = $line[0]; # the value of this is apples $thenumber = $fruit{$thefruitsname}; print "the number of $thefruitsname is $thenumber\n"; # this prints "the number of apples is " (WHY does this not work? NB + if I change $thefruitsname to "apples" (without quotation marks) the +n it does print "the number of apples is 5".) }

Background: the file fruit_names.csv will actually contain a very long list of fruit names in a particular order. The file fruit.csv will contain a much shorter list of fruit names and numbers. I want to create a list of all the fruit in this list, with their numbers, in the same order as the fruit names appear in fruit_names.csv including empty rows for fruits which do not appear in fruit.csv but which are in fruit_names.csv. This is because I have data for the amount of each fruit sold on average per week in ten different stalls, but each list of fruit (and numbers) is in a different order and doesn't contain all of the same fruits (but all fruit ARE listed in fruit_names.csv). In order to compare the ten lists, I want to create a table with all the possible fruit names in the leftmost column, and a column for each stall showing number of each fruit sold, or blank if no data exist for that fruit.

  • Comment on Getting values from a hash, using a string taken from a .csv file as the value
  • Download Code

Replies are listed 'Best First'.
Re: Getting values from a hash, using a string taken from a .csv file as the value
by choroba (Cardinal) on Feb 17, 2015 at 17:18 UTC
    If the line contains only the string apple, and you split it on comma (line 16), the newline at the end of the line stays in $line[0]. Therefore, the hash doesn't return anything for the key. Use chomp to remove the newline:
    #!/usr/bin/perl use warnings; use strict; my %fruit; open my $FRUIT, '<', 'fruit.csv' or die $!; while (<$FRUIT>) { my @line = split /,/; my($fruit_name, $number) = @line; $fruit{$fruit_name} = $number; } close $FRUIT; open my $FRUITNAMES, '<', 'fruit_names.csv' or die $!; while (<$FRUITNAMES>) { chomp; my @line = split /,/; my $thefruitsname = $line[0]; warn ": $thefruitsname"; my $thenumber = $fruit{$thefruitsname}; print "the number of $thefruitsname is $thenumber\n"; }

    Also use indentation, 3 argument open + or die, and strict as shown in the script.

    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Getting values from a hash, using a string taken from a .csv file as the value
by Tux (Canon) on Feb 17, 2015 at 17:19 UTC

    Your problem is either "ignoring newlines" or "not using a decent CSV parser". Take your pick.

    For the first, use chomp:

    my %fruit; open my $fh, "<", "fruit.csv") or die; while (<$fh>) { chomp; # THIS IS IMPORTANT HERE my ($fruit_name, $number) = split m/,/ => $_; $fruit{$fruit_name} = $number; # puts key-value pair (apples 5) in +to the hash } close ($fh); open my $fn, "<", "fruit_names.csv" or die; while (<$fn>) { chomp; # DO NOT FORGET my ($thefruitsname) = split m/,/ => $_; my $thenumber = $fruit{$thefruitsname} or die; ... }

    Enjoy, Have FUN! H.Merijn
Re: Getting values from a hash, using a string taken from a .csv file as the value
by toolic (Bishop) on Feb 17, 2015 at 17:17 UTC