Re: setting values in anonymous hash
by quidity (Pilgrim) on Nov 28, 2000 at 18:17 UTC
|
You can use map on the expanded hash to alter any undef'ined value to be equal to '' instead. As you cannot use undef as a hash key (it is turned into a string, so becomes '' (although a literal 'undef' becomes the string 'undef')) then this won't hurt any of the keys:
%new_hash = map {defined($_) ? $_ : ''} %{$ref2};
For your example you could replace all the code above with something along the lines of:
$rh_foo = {a=>undef, b=>'b_value', c=>undef, e=>'e_value'};
push @foo, { map {defined($_) ? $_ : ''} %{$rh_foo} };
foreach (keys %{$foo[0]}) {
print "$_ => ${$foo[0]}{$_}\n";
}
| [reply] [d/l] [select] |
|
|
quidity suggests:
> %new_hash = map {defined($_) ? $_ : ''} %{$ref2};
In recent versions of Perl, you can also use a simpler version that modifies the hash
in place:
map { $_ = '' unless defined } %$ref2;
This is comparable in simplicity to the original code that
involved an array instead of a hash.
| [reply] [d/l] |
|
|
map { $_ = '' unless defined } %$ref2;
To eliminate the void map, and not attack the keys (which don't need attacking),
I'd go with:
defined or $_ = "" for @$ref2{keys %$ref2};
or for 5.6 and later:
defined or $_ = "" for values %$ref2;
-- Randal L. Schwartz, Perl hacker | [reply] [d/l] [select] |
|
|
|
|
|
|
|
|
|
|
map { $_ = '' unless defined } values %$ref2;
I guess I'm just wondering why referring to hashes
in a list context is a good idea.
Update:
merlyn rightly points out this is a void usage
of map. Perusing the docs for map
led me to some insight. We want to test for values
that are undefined and change them -- sounds like a
job for grep:
for (grep {not defined} values %$ref2) {$_ = q()};
fits the bill -- it actually acts on the returned
values from grep, so no more void contexts, and
actually reads like the task desired.
| [reply] [d/l] [select] |
|
|
|
|
|
Re: setting values in anonymous hash
by snax (Hermit) on Nov 28, 2000 at 18:24 UTC
|
There comes a time when one must display one's
ignorance without fear. I suspect this is my time :)
I think I am missing something fundamental. First,
I don't see why %tmp is necessary, nor do I
I understand resetting the $k and $v
before the while loop starts over -- don't they get
reset automatically?
In other words, why wouldn't this work:
while (my $ref2 = $sth2->fetchrow_hashref()) {
while (my ($k, $v) = each %$ref2) {
$ref2->{$k} = '' if $v == undef;
}
}
?
| [reply] [d/l] |
|
|
Says snax:
> why wouldn't this work:
> $ref2->{$k} = '' if $v == undef;
It doesn't work because if $v was "hello", then you
have just scrubbed it out and replaced it with the
empty string.
You should never compare anything for equality with
undef, because 0 == undef is true,
and "fish" == undef is also true.
This is because undef behaves like 0 in a numeric
context, and so do most strings. Even
"" eq undef is true, which probably is not what you want.
The only way to check to see if something is undef
is to use the defined operator:
$ref2->{$k} = '' if not defined $v;
| [reply] [d/l] |
|
|
| [reply] |
|
|
while (my ($k, $v) = each %$ref2) {
$ref2->{$k} = '' if (!defined $ref2->{$k});
}
push @{ $tablist{$user_table} }, $ref2;
Cheers..
PPS: and even better this way, thanks!!!!
for (keys %$ref2) {
$ref2->{$_} = '' if (!defined $ref2->{$_});
}
push @{ $tablist{$user_table} }, $ref2;
PPPS: maybe down to one line if I was using 5.5! (untested this last one)
$ref2->{$_} = '' unless (defined $ref2->{$_}) for (keys %$ref2);
| [reply] [d/l] [select] |