•Re: One liner to Check and undef hash elements
by merlyn (Sage) on Apr 16, 2003 at 02:13 UTC
|
my $hash_has_non_undef = sub { while (my ($key, $value) = each %hash)
+{ return 1 if defined $value } 0 }->();
Problem 2:
@hash{keys %hash} = ();
-- Randal L. Schwartz, Perl hacker
Be sure to read my standard disclaimer if this is a reply. | [reply] [Watch: Dir/Any] [d/l] [select] |
|
Nice! I knew there had to be a better way. Regarding problem 1, what exactly does ->() do? I know that without it, a coderef would be returned, and with it, the result is returned. But how does it work? Does it evaluate the sub on the spot or in the moment I access $hash_has_non_undef?
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
| [reply] [Watch: Dir/Any] |
|
| [reply] [Watch: Dir/Any] |
|
Doh, I knew there was a single step approach for Nr.2.. it just wouldn't occur to me last night.
I'm not sure I like your approach to the first one though - using a subref to get around the lack of control in naked blocks seems to hackish. I'm not really happy with my own alternative, either:
my $hash_has_non_undef = do {
local $_;
my $found = 0;
defined && ($found++, last)
while (undef, $_) = each %hash;
$found;
};
But without Perl 6 junctions there's not much that can be done about it if you need shortcircuiting..
Makeshifts last the longest. | [reply] [Watch: Dir/Any] [d/l] |
|
Well, the non-sub way could look like this:
my $hash_has_non_undef = do { my $found; until($found or not (undef, m
+y $v) = each %hash) { $found = defined $v } $found };
I mean, that's the way we had to do it in Pascal. Stupid boolean flag variables all over the place because they wouldn't let us exit blocks. {grin}
Doh! As I'm staring at this, I realize the $v can do double duty.
my $hash_has_non_undef = do { my $v; until($v or not (undef, $v) = eac
+h %hash) { $v = defined $v } $v };
But that's optimized for Golf, not for maintenance. Ick.
-- Randal L. Schwartz, Perl hacker
Be sure to read my standard disclaimer if this is a reply. | [reply] [Watch: Dir/Any] [d/l] [select] |
|
Re: One liner to Check and undef hash elements
by Aristotle (Chancellor) on Apr 16, 2003 at 02:04 UTC
|
# 1.)
scalar grep defined, values %$hash;
# 2.)
undef $_ for values %$hash;
At 2.), I interpreted your question as in just emptying all slots, without removing their keys.
Makeshifts last the longest. | [reply] [Watch: Dir/Any] [d/l] |
Re: hash problem
by crenz (Priest) on Apr 15, 2003 at 23:15 UTC
|
#1.
if ((scalar grep {defined} values %{$hash}) == 0) {
# all values are undef
}
#2.
$hash = { map {$_ => undef} keys %{$hash} };
# now empty
Update: Changed > 0 to == 0, since the poster asked for "check if empty"
Update: Fixed precedence problem (pointed out by original poster). Works now. | [reply] [Watch: Dir/Any] [d/l] |
|
Hi crenz,
thanks for you reply. #2 works very nicely,
but I can't make #1 work. Your code prints
"empty" for both of these hashes.
$hash->{'a'} = 1;
$hash->{'b'} = undef;
$hash->{'c'} = undef;
$hash->{'d'} = undef;
if (scalar grep {defined} values %{$hash} == 0) {
print "empty\n";
}
$hash->{'a'} = undef;
$hash->{'b'} = undef;
$hash->{'c'} = undef;
$hash->{'d'} = undef;
if (scalar grep {defined} values %{$hash} == 0) {
print "empty\n";
}
| [reply] [Watch: Dir/Any] [d/l] |
Re: Checking and undef'in hash elements in one step?
by grantm (Parson) on Apr 16, 2003 at 01:10 UTC
|
if(scalar @{[ delete @hash{keys %hash} ]}) {
print "Hash was not empty\n";
}
else {
print "Hash was empty\n";
}
The delete function returns a list of the deleted values. If there were no keys in the hash then the list will be empty. I found that if the hash contained one key with a value of undef then scalar delete @hash{keys %hash} evaluated to false - hence the anonmous array gymnastics.
My code is actually checking whether the hash was empty (and in the same step emptying it), but to go back to your original question, you define empty as "all elements are undef" which is a mighty unusual definition of empty. Surely if it's empty, there are no elements.
You may be confused by the fact that refering to a hash key that does not exist returns undef. If the hash key does exist, but its value is undef, then the hash is not empty - it has at least one key. The 'exists' function is what you'd use to check for the existence of a particular key.
If your hash might have undefined values but you just want to know if there are any defined values, you could say:
if(grep defined($_), values %hash) {
...
}
| [reply] [Watch: Dir/Any] [d/l] [select] |
|
use strict;
use warnings;
use Data::Dumper;
my $hash;
$hash->{'a'} = 1;
$hash->{'b'} = undef;
$hash->{'c'} = undef;
$hash->{'d'} = undef;
unless (grep {defined $$hash{$_} xor $$hash{$_}=undef} keys %{$hash} )
+ { print "empty\n";}
else { print "Not empty\n"; }
print Dumper \$hash;
-enlil | [reply] [Watch: Dir/Any] [d/l] |
Re: Checking and undef'in hash elements in one step?
by l2kashe (Deacon) on Apr 16, 2003 at 00:22 UTC
|
Update: The first line is why this node is garnishing negative XP. Its wrong for a few reasons..both reasons are within the unless...
First off unless will only evaluate to true if the EXPR inside returns something other than '0', an empty sting '', or undef
Second is the NULL. In this context I was attempting to use it as a alias for '0' which is what perl does, but that was wrong because if we do 'unless( values(%hash) );' that works as well. If we had applied 'use strict;' to this code it would have broke as NULL is a bareword in this situation.
Justifications:
First: I've been coding a bunch of C lately as should be readily apparent to whomever knows C in the bunch. I just didn't fully context switch to perl when whipping out this code.
Second: There was a thread ( I will attempt to find and link to) which raised an interesting situation where when calling values on a newly created hash ( cant remember if it was actually a ref to a hash or not), the values would be autovivified. In that situation I ended up suggesting doing 'unless( join('', values %hash) );' which was the only way to consistantly check to see if the hash really had anything in it.
Sorry for the bad code, but I guess we can stop downvoting this node, and simply use it as an example for .... something somewhere I'm sure..
# will print "no keys" if all values are undef..
print "no keys\n" unless( values(%hash) != NULL );
# to resest a hash..
%hash = ();
# or if you are paranoid
undef(%hash) && %hash = ();
Happy hacking
MMMMM... Chocolaty Perl Goodness..... | [reply] [Watch: Dir/Any] [d/l] |
|
| [reply] [Watch: Dir/Any] [d/l] |
|
Perhaps saying that NULL isn't a keyword would be more constructive, or that he meant undef instead.
cb reference!: now, what are the odds I log in in the morning to find all my posts mysteriously downvoted?
UPDATE:Awww. not downvoted at all.
feanor_269
| [reply] [Watch: Dir/Any] |
|
It was more to display the idea .. but its syntax is correct and in testing provided acurate results.. I've now garnished quite a few negative XP for this nodelet.. Thanks for at least responding to the post...
Now why dont people like this??
should it have said "no values were defined?" which matches what was asked for?.. should I have left it as unless( values(%hash)) ???
after testing some more I now see that the values(%hash) is sufficient.. I stand corrected and accept the negative XP..
/me dohs and hangs his head in shame...
MMMMM... Chocolaty Perl Goodness.....
| [reply] [Watch: Dir/Any] |
|
|
A Perl line with syntax error is still Perl.
To be frank, I don't see the point of your last line, that Q&A. It should not be too difficult for people to be nice to each other. Make pointless comment (I point to your last line) is an insult to the merit of the poster, and the community at large. I don't see this funny at all.
I read your disclaimer, but it does not entitle you to be rude, or gives you the excuse to be rude. Doesn't matter whether it is for a good purpose or a bad one, the way you expressed yourself is rude, and there is no need to put things in that way.
I point out this to you for your benefit, to be sincere. I don't jump on you because of this single incident, but you have been doing this to people from time to time.
Well, I understand how you behave yourself is really your decision.
| [reply] [Watch: Dir/Any] |
|
As you said the syntax is wrong, let me tell you now, from a pure syntax point of view, this is perfectly correct Perl syntax.
Didn't you realize that NULL could be a constant?
use strict;
use constant NULL => "";
my @a = (1,2,3);
my @b = ();
my @c = ("");
print "a is empty: " . is_null(@a), "\n";
print "b is empty: " . is_null(@b), "\n";
print "c is empty: " . is_null(@c);
sub is_null {
my @a = @_;
(@a == NULL) ? "true" : "false";
}
| [reply] [Watch: Dir/Any] [d/l] |
Re: One liner to Check and undef hash elements
by Anonymous Monk on Apr 16, 2003 at 13:29 UTC
|
Wow! You guys never cease to amaze me. thanks
to everyone.
Michael | [reply] [Watch: Dir/Any] |