How to grep undefined values in an array? - perl

I have an array with an undefined value:
[0] 0.1431,
[1] undef
I then later push this value onto an array, and Perl doesn't warn me about the uninitialized values (I cannot imagine why someone would want this to happen without a warning or die, even when I have use autodie ':all' set, but that's another story)
So I try and grep on these arrays to prevent pushing undef values onto arrays, thus:
if (grep {undef} #array) {
next
}
But, this doesn't catch the value.
How can I grep for undefined values in Perl5?

grep for not defined instead:
use warnings;
use strict;
my #array = (0, undef, undef, 3);
if (grep {! defined} #array) {
print "undefined values in array\n";
}
There are several reasons as to why you'd want to have/allow undefined values in an array. One such beneficial scenario is when passing in positional parameters to a function.

Why not prevent the values from being added in the first place?
Replace
push #array, LIST;
with
push #array, grep defined, LIST;
If it's specifically a scalar, you could also use
push #array, $scalar if defined($scalar);

You can use defined to get rid of undefined items:
use warnings;
use strict;
use Data::Dumper;
my #a1 = (1,2,3,undef,undef,4);
print Dumper(\#a1);
my #a2 = grep { defined } #a1;
print Dumper(\#a2);
Output:
$VAR1 = [
1,
2,
3,
undef,
undef,
4
];
$VAR1 = [
1,
2,
3,
4
];

Related

Perl hash, array and references

I have this 3 lines of code in a sub and I'm trying to write them together on one line only.. but I'm quite lost
my %p = #_;
my $arr = $p{name};
my #a = #$arr;
what's the correct way of doing this?
thank you!
my %p = #_;
#_ is assumed to contain key-value pairs which are then used to construct the hash %p.
my $arr = $p{name};
The argument list is assumed to have contained something along the lines of name, [1, 2, 3,] so that $p{name} is an reference to an array.
my #a = #$arr;
Dereference that array reference to get the array #.
Here is an invocation that might work with this prelude in a sub:
func(this => 'that', name => [1, 2, 3]);
If you want to reduce the whole prelude to a single statement, you can use:
my #a = #{ { #_ }->{name} };
as in:
#!/usr/bin/env perl
use strict;
use warnings;
use YAML::XS;
func(this => 'that', name => [1, 2, 3]);
sub func {
my #a = #{ { #_ }->{name} };
print Dump \#a;
}
Output:
---
- 1
- 2
- 3
If the array pointed to by name is large, and if you do not need a shallow copy, however, it may be better to just stick with references:
my $aref = { #_ }->{ name };
OK so what you're doing is:
Assign a list of elements passed to the sub, to a hash.
extract a value from that hash (that appears to be an array reference)
dereference that into a standalone array.
Now, I'm going to have to make some guesses as to what you're putting in:
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
sub test {
my %p = #_;
my $arr = $p{name};
my #a = #$arr;
print Dumper \#a;
}
my %input = ( fish => [ "value", "another value" ],
name => [ "more", "less" ], );
test ( %input );
So with that in mind:
sub test {
print join "\n", #{{#_}->{name}},"\n";
}
But actually, I'd suggest what you probably want to do is pass in the hashref in the first place:
#!/usr/bin/perl
use warnings;
use strict;
use Data::Dumper;
sub test {
my ( $input_hashref ) = #_;
print Dumper \#{$input_hashref -> {name}};
}
my %input = ( fish => [ "value", "another value" ],
name => [ "more", "less" ], );
test ( \%input );
Also:
Don't use single letter variable names. It's bad style.
that goes double for a and b because $a and $b are for sorting. (And using #a is confusing as a result).

Size of array inside hash

EDIT: Providing code as per demand from mppac:
I wanted the length of array inside hash.
Why is below showing undef?
$ >cat test.pl
#!/usr/bin/perl
use Data::Dumper;
my %static_data_key = (
'NAME' =>['RAM','SHYAM','RAVI','HARI'],
);
print Dumper(\%static_data_key);
$ >./test.pl
$VAR1 = {
'NAME' => [
'RAM',
'SHYAM',
'RAVI',
'HARI'
]
};
The return value of a Perl array in scalar context is the array's size. For example:
my #array = ( 'a', 'b', 'c' );
my $size = #array;
print "$size\n";
This code will print '3'. When dereferenced, anonymous arrays share this characteristic:
my $aref = [ 'a', 'b', 'c' ];
print $aref, "\n"; # ARRAY(0x1e33148)... useless in this case.
my $size = #{$aref}; # Dereference $aref, in scalar context.
print "$size\n"; # 3
The code I'm demonstrating takes a few unnecessary steps to lend clarity. Now consider this:
print scalar #{[ 'a', 'b', 'c']}, "\n"; # 3
Here we're constructing an anonymous array and immediately dereferencing it. We obtain its return value in scalar context, which happens to be 3.
Finally, let's put that anonymous array into a hash:
my %hash = (
NAME => [ 'joseph', 'frank', 'pete' ]
);
print scalar #{$hash{NAME}}, "\n";
Read that last line from the middle outward; first we obtain the value stored the NAME element within %hash. That is a reference to an anonymous array. So we dereference it with #{ ..... }. And we use scalar to force scalar context. The output is 3.
#!/usr/bin/perl
# your code goes here
use strict;
use warnings;
my %static_data_key = (
'NAME' =>['RAM','SHYAM','RAVI','HARI'],
);
print scalar #{$static_data_key{'NAME'}};
Demo

An array and a variable as parameters in subroutine in Perl

Consider:
sub abc()
{
}
abc(#array, $a);
How do I access #array and $a in subroutine abc()?
I know about $_[0] and $_[1], but I wasn't sure if I can use it for arrays.
You access a sub's arguments with the #_ array. The first argument is $_[0], the second - $_[1], etc. In this particular case, your array will be unrolled to list of its elements, so $_[0] is $array[0], $_[1] is $array[1] and then after all those elements, last element of #_ will be the value of $a.
If you want to avoid unrolling that always happens when you use an array in a list context, use a reference to the array instead. References to arrays and hashes are created using \. So call your function like:
abc(\#array, $a);
After that, $_[0] will have reference to #array and $_[1] will be $a. To access array elements through reference, use -> operator. $_[0]->[2] is same as $array[2]. Actually you can even drop -> as long as it is between brackets, so $_[0][2] will work too. See more details on references in perlref.
You have two options:
Pass the scalar variable first (the dirty way)
abc($a, #array);
Then receive the parameters in subroutine as
my ($a, #array) = #_;
Pass your array as reference by adding a backslash before the array variable (recommended)
abc(\#array, $a);
Then receive the parameters in subroutine as
my ($array_ref, $a) = #_;
And dereference the $array_ref
my #array = #$array_ref;
More information about perlref.
The other answers explained the two basic approaches. However, it is important to note that there is a big difference between the two: When you pass an array by reference, any changes you make to it also change the original array. Here is an example:
use warnings;
use strict;
my #array = (1, 2, 3, 4, 5);
sub by_ref
{
my $array_ref = $_[0];
#$array_ref = (0, 0, 0);
print "Array inside by_ref: #$array_ref\n";
}
sub by_val
{
my #array_copy = #_;
#array_copy = (0,0,0);
print "Array inside by_val: #array_copy\n";
}
by_val(#array);
print "Original array after calling by_val: #array\n";
by_ref(\#array);
print "Original array after calling by_ref: #array\n";
If you do pass by reference, you need to keep this behavior in mind, making a copy of the referenced array if you don't want changes made in your sub to affect the original.
It would be nice if you pass the array reference instead of an array as mentioned by Oleg V. Volkov like
sub abc()
{
my ( $array, $a ) = #_; #receiving the paramters
my #arr = #{$array}; # dereferencing the array
}
abc(\#array,$a);

Dereferencing a list reference in hash element

Can someone finish this for me and explain what you did?
my %hash;
#$hash{list_ref}=[1,2,3];
#my #array=#{$hash{list_ref}};
$hash{list_ref}=\[1,2,3];
my #array=???
print "Two is $array[1]";
#array = #{${$hash{list_ref}}};
(1,2,3) is a list.
[1,2,3] is a reference to a list an array (technically, there's no such thing in Perl as a reference to a list).
\[1,2,3] is a reference to a reference to an array.
$hash{list_ref} is a reference to a reference to an array.
${$hash{list_ref}} is a reference to an array.
#{${$hash{list_ref}}} is an array.
Since a reference is considered a scalar, a reference to a reference is a scalar reference, and the scalar dereferencing operator ${...} is used in the middle step.
Others have pretty much already answered the question, but more generally, if you are ever confused about a data structure, use Data::Dumper. This will print out the structure of the mysterious blob of data, and help you parse it.
use strict; #Always, always, always
use warnings; #Always, always, always
use feature qw(say); #Nicer than 'print'
use Data::Dumper; #Calling in the big guns!
my $data_something = \[1,2,3];
say Dumper $data_something;
say Dumper ${ $data_something };
Let's see what it prints out...
$ test.pl
$VAR1 = \[
1,
2,
3
];
$VAR1 = [
1,
2,
3
];
From the first dump, it appears that $data_something is a plain scalar reference to an array reference. That lead me to add the second Dumper after I ran the program the first time. That showed me that ${ $data_something } is now a reference to an array.
I can now access that array like this:
use strict; #Always, always, always
use warnings; #Always, always, always
use feature qw(say); #Nicer than 'print'
use Data::Dumper; #Calling in the big guns!
my $data_something = \[1,2,3];
# Double dereference
my #array = #{ ${ $data_something } }; #Could be written as #$$data_something
for my $element (#array) {
say "Element is $element";
}
And now...
$ test.pl
Element is 1
Element is 2
Element is 3
It looks like you meant:
my $hash{list_ref} = [1,2,3];
and not:
$hash{list_ref} = \[1,2,3];
That latter one got you an scalar reference of a array reference which really doesn't do you all that much good except add confusion to the situation.
Then, all you had to do to refer to a particular element is $hash{list_ref}->[0]. This is just a shortcut for ${ $hash{list_ref} }[0]. It's easier to read and understand.
use strict;
use warnings;
use feature qw(say);
my %hash;
$hash{list_ref} = [1, 2, 3];
foreach my $element (0..2) {
say "Element is " . $hash{list_ref}->[$element];
}
And...
$ test.pl
Element is 1
Element is 2
Element is 3
So, next time you are confused about what a particular data structure looks like (and it happens to the best of us. Well... not the best of us, It happens to me), use Data::Dumper.
my %hash;
#$hash{list_ref}=[1,2,3];
#Putting the list in square brackets makes it a reference so you don't need '\'
$hash{list_ref}=[1,2,3];
#If you want to use a '\' to make a reference it is done like this:
# $something = \(1,2,3); # A reference to a list
#
# or (as I did above)...
#
# $something = [1,2,3]; # Returns a list reference
#
# They are the same (for all intent and purpose)
print "Two is $hash{list_ref}->[1]\n";
# To make it completely referenced do this:
#
# $hash = {};
# $hash->{list_ref} = [1,2,3];
#
# print $hash->{list_ref}[1] . "\n";
To get at the array (as an array or list) do this:
my #array = #{ $hash{list_ref} }
[ EXPR ]
creates an anonymous array, assigns the value returned by EXPR to it, and returns a reference to it. That means it's virtually the same as
do { my #anon = ( EXPR ); \#anon }
That means that
\[ EXPR ]
is virtually the same as
do { my #anon = ( EXPR ); \\#anon }
It's not something one normally sees.
Put differently,
1,2,3 returns a list of three elements (in list context).
(1,2,3) same as previous. Parens simply affect precedence.
[1,2,3] returns a reference to an array containing three elements.
\[1,2,3] returns a reference to a reference to an array containing three elements.
In practice:
my #data = (1,2,3);
print #data;
my $data = [1,2,3]; $hash{list_ref} = [1,2,3];
print #{ $data }; print #{ $hash{list_ref} };
my $data = \[1,2,3]; $hash{list_ref} = \[1,2,3];
print #{ ${ $data } }; print #{ ${ $hash{list_ref} } };

Why does map return an empty array?

I have a problem in Perl I don't understand. I stripped it down to this very short code.
Why does Perl's map function return an empty array? Shouldn't it return an array with 9 undefs?
sub mySub{
return;
}
my #arr = (1 .. 9);
my #arr2 = map( mySub($_), #arr );
print #arr . ' ' . #arr2, "\n";
It prints "9 0".
It is probably something simple, but perldoc is not helping.
The more general answer to your question is this: when return is used without an argument, the value it returns depends on the calling context:
list context returns an empty list
scalar context returns an undefined value
For example:
use strict;
use warnings;
use Data::Dumper;
my (#list);
sub mySub { return }
#list = map( mySub($_), 1..2); print Dumper(\#list);
#list = map(scalar mySub($_), 1..2); print Dumper(\#list);
Output:
$VAR1 = [];
$VAR1 = [
undef,
undef
];
You subroutine is not returning undef, it is returning an empty list. 9 times and empty list is still an empty list.
Try explicitly returning undef and the output will be different.
Try this
use strict;
use warnings;
sub mySub{
return undef;
}
my #arr = (1,2,3,4,5,6,7,8,9);
my #arr2 = map(&mySub, #arr);
print #arr." ".#arr2;
If you need to get list containing undefs, you need to return undef explicitly. The thing is that map calls your mySub in array context (check what wantarray gives you from this sub). return statement essentially gives back an empty list each time your sub is called, which results in empty array in total