2

I have a Perl script that reads in a CSV file, changes the columns names of the original, adds new ones (output CSV column names are stored in the array, header_line), adds new field values for each row read, and then writes out a new CSV file.

Thanks to a comment by @harleypig on my last question, I'd like to use:

$csv_i->column_names( @header_line);
$row = $csv_i->getline_hr($fh_i)

because this lets me easily access row fields using meaningful names rather than magic numbers. For example:

$row->{ 'name' } = get_fullname($row->{ 'name' });

The only problem now is, what's the best way to write out the line? Previously, I used:

$csv_o->print( $fh_o, $row ); 

But that fails because it expects an array ref. How do I write out the hash ref using the csv_o object?

2 Answers 2

4

Use a hash slice:

$csv_o->print( $fh_o, [ @$row{@header_line} ] );

The map version works too, but the slice is faster:

use Benchmark 'cmpthese';

my @header_line = qw(a b c d e f g);
my $row = { map { $_ => $_ } @header_line };

my $array;

cmpthese(-3, {
  slice => sub {
    $array = [ @$row{@header_line} ];
  },

 map => sub {
    $array = [ map { $row->{$_} } @header_line ];
  },
});

gives me:

          Rate   map slice
map   282855/s    --  -42%
slice 487898/s   72%    --
Sign up to request clarification or add additional context in comments.

Comments

1

From a quick look at the docs, I don't think you can easily. You'd have to turn the hashref back into the (column-ordered) array, something like:

$csv_o->print( $fh_o, [ map { $row->{$_} } @header_line ] ); 

1 Comment

Thanks, this works fine too; will go with the hash slice though as this seems to have the edge.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.