Beefy Boxes and Bandwidth Generously Provided by pair Networks
No such thing as a small change

||= in Hash Slice

by Brovnik (Hermit)
on Jan 06, 2009 at 11:48 UTC ( #734413=perlquestion: print w/replies, xml ) Need Help??
Brovnik has asked for the wisdom of the Perl Monks concerning the following question:

I want to do some hash slice assigns.
my $key_fields = [ qw( trade_ref sec_code lot of other fields ) ]; my $copy_fields = [ qw( item_period other fields) ]; my $audit = {}; @{$audit}{@$key_fields} = @{$item}{@$key_fields}; # $item is a hashref with some but maybe not all of the # above fields defined $audit->{$_} = $item->{$_} || '' for @$copy_fields;
Alternatively :
@{$audit}{@$copy_fields} = @{$item}{@$copy_fields}; $audit->{$_} ||= '' for @$copy_fields;
These work, but I really want to do :
@{$audit}{@$copy_fields} = @{$item}{@$copy_fields} || '';
to make sure there are no undefs. Can I do the above as a single Hash slice assignment ?

Replies are listed 'Best First'.
Re: ||= in Hash Slice
by ikegami (Pope) on Jan 06, 2009 at 12:40 UTC

    Three ways:

    @{$audit}{@$copy_fields} = map $_ || '', @{$item}{@$copy_fields};
    $_ ||= '' for @{$audit}{@$copy_fields} = @{$item}{@$copy_fields};
    no warnings 'uninitialized';

    I only recommend the first.

Re: ||= in Hash Slice
by Corion (Pope) on Jan 06, 2009 at 12:00 UTC

    I'm not aware of a convenient per-item combination. I hear that Perl 6 will have "hyper-operators" for that, when it reaches a stable release version >= 1.0.

    I'd do that with a map, as I always use map when transforming one list into another:

    @{$audit}{@$copy_fields} = map { defined $item->{$_} ? $item->{$_} : ' +' } @$copy_fields;

    Your code will happily replace a value of "0" by "", and I guess that's not intended.

      Yup, I guess that works, but I was hoping for something a bit more elegant.
      @{$audit}{@$copy_fields} = map { $item->{$_} || '' } @$copy_fields;
      Is probably the nearest I'll get.
      P.S. The '' vs. 0 difference is irrelevant here in my case, I just want avoid undefs.
        That may not, probably won't, work in all cases ... consider when the value of $item->{$_} is 0: in this case, the wanted value of 0 will be overwritten by the empty string, since $item->{$_} is, from a perl POV, false. Hence Corions suggestion, tho' not quite what you were seeking, is better.

        A user level that continues to overstate my experience :-))
Re: ||= in Hash Slice
by gone2015 (Deacon) on Jan 06, 2009 at 12:08 UTC

    I don't think so. But this should work:

    @{$audit}{@$copy_fields} = map { defined($_) ? $_ : '' } @{$item}{@$ +copy_fields} ;
      $_ here is the key, which will always be defined, so the defined($item->{$_}) as above is needed.
      Edit: Oops, misread the reply, apologies.
        No it's not. It's the value.
Re: ||= in Hash Slice
by JavaFan (Canon) on Jan 06, 2009 at 12:33 UTC
    Can I do the above as a single Hash slice assignment ?
    No. The problem is the '||' operator which provides scalar context to its LHS argument.

    You'll have to type 'map' if you want a map... ;-)

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://734413]
Approved by Corion
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others imbibing at the Monastery: (5)
As of 2017-06-28 22:11 GMT
Find Nodes?
    Voting Booth?
    How many monitors do you use while coding?

    Results (649 votes). Check out past polls.