开发者

How to set default values?

Let's say I have a hash like this

my %profile = (
    building            => $p->{account}->{building},
    email               => $p->{account}->{email},
    phone               => $p->{account}->{phone},
    );

The variables in $p can have all sorts of values when they have not been defined. I have atleast seen undef ~ ''.

How do I assign a value of -1 to e.g. $profile{building} if $p->{account}->{building} have one of these strange default values?

Are there any clever Perl way to do that?

Update: Any of the 开发者_开发技巧values can take on any of the strange default values undef ~ ''.


I would add a function:

my %profile = (
    building            => scrub($p->{account}->{building}),
    email               => scrub($p->{account}->{email}),
    phone               => scrub($p->{account}->{phone}),
    );

and implement the default-filtering logic in the function.

Or, better yet, pre-apply the logic to $p so that you know that $p has reasonable values.


So, if I understand you correctly, you have a bunch of bogus things being used as flags for "use the default". I am not sure if you want to translate all of these to -1 or to field specific values. I'll assume multiple values, just to make things trickier.

# Make a hash of the wanted values
my %default_values = (
    building => -1,
    email    => 'N/A',
    phone    => 'unlisted',
);

# Make a hash of the values to replace.
# Skip undef, we have to check that separately
my %bogus_values = map {$_ => undef} ('', '~', 0);

# Copy the goodies into your final structure
my  %profile = map { 
    my $val = $p->{account}{$_};
    $val = $default_values{$_}
        if( not defined $val 
            or exists $bogus_values{$_}
        );
    $_ => $val;
} keys %default_values;


# Or copy them another way
my %profile = %default_values;
$profile{$_} = $p->{account}{$_}
    for grep {
        defined $p->{account}{$_}
        and not exists $bogus_values{$_}
    } keys %default_values;


Starting from Perl 5.10, you can use smart matching:

my @vals = (undef, '~', "");
$profile{building} = $p->{account}{building} ~~ @vals ? -1 : $p->{account}{building};


If using 5.10 or higher I would go with @eugene's solution. Otherwise ...

For untrue values (undef, '', 0) you can do

building => $p->{account}->{building} || -1

For true values you will have to check explicitly, perhaps with a regex:

building => !($p->{account}->{building} =~ m/~|char2|char3/)
            ? $p->{account}->{building}
            : -1

Combining these

building => $p->{account}->{building} || !($p->{account}->{building} =~ 
                                                             m/~|char2|char3/)
            ? $p->{account}->{building}
            : -1

Alternatively, to make this simpler and to facilitate testing and reusability you can extract this logic to a sub:

sub scrub {
    my $value = shift;

    if (!$value or $value =~ m/~|char2|char3/) {
        return -1;
    }

    return $value;
}

And then

my %profile = (
    building            => scrub( $p->{account}->{building} ),
    email               => scrub( $p->{account}->{email} ),
    phone               => scrub( $p->{account}->{phone} ),
    );


This sort of thing will take care of FALSE values (like undef or '' or 0 or '0' or anything else I missed):

my %profile = (
    building            => $p->{account}->{building} || -1,
    email               => $p->{account}->{email} || 'N/A',
    phone               => $p->{account}->{phone} || -1,
    );

You can also use the defined-or operator //, which will only use the default value if undef is on the left side.


Or to take care of other values:

my %bad_values_hash = map { $_ => 1 } ('~', ''); # Put your bad values in here

my %profile = (
    building            => ($bad_values_hash{$p->{account}->{building}} ? -1 : $p->{account}->{building}) // -1,
    email               => ($bad_values_hash{$p->{account}->{email}} ? 'N/A' : $p->{account}->{email}) // 'N/A',
    phone               => ($bad_values_hash{$p->{account}->{phone}} ? -1 : $p->{account}->{phone}) // -1,
    );

(May I suggest refining the design so that it uses more consistent default values?)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜