Combine scalar array references in perl - perl

I have a datastructure like:
$hashRef->{"key1"}->{"key2"} = ['1','2','3']
This $hashRef gets new values every iteration of the for loop. I am trying to append all of these to produce an output like so:
$hashRef->{"key1"}->{"key2"} = ['loop1.out1','loop1.out2','loop1.out3','loop2.out1','loop2.out2','loop2.out3',...]
loop1.ou1 is symbolic for the first output from loop 1 and not intended to be printed.
Is this possible?

Hope this is what you want:
map {
push(#{$hashRef->{"key1"}->{"key2"}}, "loop$count.out".$_);
} #{$arr2};
$count is the loop number.
#{$arr1} is the incoming array.
Thanks,
Anoop

You may use push to append new values to the array:
push( #{$hashRef->{"key1"}->{"key2"}}, 'loop1.out1','loop1.out2','loop1.out3');
$aData = [ 'loop2.out1','loop2.out2','loop2.out3' ];
push( #{$hashRef->{"key1"}->{"key2"}}, #$aData);
print join(",",#{$hashRef->{"key1"}->{"key2"}} ),"\n";

Related

Perl find out if X is an element in an array

I don't know why small things are too not working for me in Perl. I am sorry for that.
I have been trying it around 2 hrs but i couldn't get the results.
my $technologies = 'json.jquery..,php.linux.';
my #techarray = split(',',$technologies);
#my #techarray = [
# 'json.jquery..',
# 'php.linux.'
# ];
my $search_id = 'json.jquery..';
check_val(#techarray, $search_id);
And i am doing a "if" to search the above item in array. but it is not working for me.
sub check_val{
my #techarray = shift;
my $search_id = shift;
if (grep {$_ eq $search_id} #techarray) {
print "It is there \n";
}else{
print "It is not there \n";
}
}
Output: It always going to else condition and returns "It is not there!" :(
Any idea. Am i done with any stupid mistakes?
You are using an anonymous array [ ... ] there, which as a scalar (reference) is then assigned to #techarray, as its only element. It is like #arr = 'a';. An array is defined by ( ... ).
A remedy is to either define an array, my #techarray = ( ... ), or to properly define an arrayref and then dereference when you search
my $rtecharray = [ .... ];
if (grep {$_ eq $search_id} #$rtecharray) {
# ....
}
For all kinds of list manipulations have a look at List::Util and List::MoreUtils.
Updated to changes in the question, as the sub was added
This has something else, which is more instructive.
As you pass an array to a function it is passed as a flat list of its elements. Then in the function the first shift picks up the first element,
and then the second shift picks up the second one.
Then the search is over the array with only 'json.jquery..' element, for 'php.linux.' string.
Instead, you can pass a reference,
check_val(\#techarray, $search_id);
and use it as such in the function.
Note that if you pass the array and get arguments in the function as
my (#array, $search_id) = #_; # WRONG
you are in fact getting all of #_ into #array.
See, for example, this post (passing to function) and this post (returning from function).
In general I'd recommend passing lists by reference.

perl, function only printing first element of the array

I have an array that has several elements on it but when I pass the array as a parameter to a function and then call the function it only prints out the first element of the array multiple times. For example
my $element;
my $random_variable = "Testing";
my #the_array = ("hello", "bye", "hey");
foreach $element(#the_array)
{
PrintFunction(#the_array, $random_variable)
}
sub PrintFunction{
my ($the_array, $random_variable) = #_;
// other code here
print $the_array . "\n";
}
The result I get from this is
hello
hello
hello
The result I want is to print all the elements of the array as
hello
bye
hey
Change:
PrintFunction(#the_array, $random_variable)
to:
PrintFunction($element, $random_variable)
Your code passes the entire array to the sub, then you only print the 1st element of the array each time because you use the scalar variable $the_array inside the sub. Since foreach grabs each element of the array, you probably meant to use $element.
Add Print #_; to your sub to see what is passed to it. You will see:
hellobyeheyTesting
hellobyeheyTesting
hellobyeheyTesting
It means you are passing the entire array followed by the $random_variable. Therefore, $the_arrayin the sub will be always the first elements of #the_array which is hello. To fix that, you should pass each element of array iteratively by
foreach $element(#the_array)
{
PrintFunction(#element, $random_variable)
}

Count hash values while using Data::Dumper

I need to find the count of values (ie abc1) in a Perl hash and if > 4 run run an internal command within a IF block. I just need to figure out the concept of how to count # of values.
(I could leave a code sample of what I've attempted but that would just result in uncontrolled laughter and confusion)
I am using Data::Dumper, and utilizing the following format to store key/value in hash.
push #{$hash{$key}}, $val;
A print of hash gives :
$ print Dumper \%hash;
$VAR1 = {
'5555' => [
'abc1',
'abc1',
'abc1'
]
};
Please let me know how to get the count.
Thanks in advance.
Well, do you want to count that particular string, or the number of elements?
my $count = #{$hash{$key}}; # get the size of the array (all elements)
my %num;
for my $val (#{$hash{$key}}) {
$num{$val}++; # count the individual keys
}
print "Number of 'abc1': $num{'abc1'}\n";
The number of values in a hash is the same as the number of keys. What you are after, though, is the number of elements in an array (referenced from a hash value). To get the size of an array, just use it in scalar context. For an array reference, you have to dereference it first:
my $count = #{ $hash{$key} };

Iterating over data structure

I am trying to iterate over this data structure:
$deconstructed->{data}->{workspaces}[0]->{workspace}->{facts}[0]->{code}
where fact[0] is increasing. It's several files I am processing so the number of {facts}[x] varies.
I thought this might work but it doesn't seem to be stepping up the $iter var:
foreach $iter(#{$deconstructed->{data}->{workspaces}[0]->{workspace}->{facts}}){
print $deconstructed->{data}->{workspaces}[0]->{workspace}->{facts}[$iter]->{code}."\n";
}
I'm totally digging data structures but this one is stumping me. Any advice what might be wrong here?
$iter is being set to the content of each item in the array not the index. e.g.
my $a = [ 'a', 'b', 'c' ];
for my $i (#$a) {
print "$i\n";
}
...prints:
a
b
c
Try:
foreach $iter (#{$deconstructed->{data}->{workspaces}[0]->{workspace}->{facts}}){
print $iter->{code}."\n";
}
$iter is not going to be an index that you can subscript the array with, it is rather the current element of the array. So I guess you should be fine with:
$iter->{code}
Your $iter contains the data sctructure. What you basiclly want is:
foreach my $elem ( #{$deconstructed->{data}->{workspaces}[0]->{workspace}->{facts}} ){
print $elem->{code};
}
or:
foreach my $iter ( 0 .. scalar #{$deconstructed->{data}->{workspaces}[0]->{workspace}->{facts}} ){
print $deconstructed->{data}->{workspaces}[0]->{workspace}->{facts}[$iter]->{code}."\n";
}
Since you are looping over the array, your misnamed $iter is the value you are looking for, not an index.
If you want to loop over the indexes instead, do:
foreach $iter ( 0 .. $#{$deconstructed->{data}->{workspaces}[0]->{workspace}->{facts}} ) {
print "Index $iter: ",
$deconstructed->{data}->{workspaces}[0]->{workspace}->{facts}[$iter]->{code}."\n";
}
Also note that you can drop -> between two [] or {}:
$deconstructed->{data}{workspaces}[0]{workspace}{facts}[$iter]{code}
I recommend reading http://perlmonks.org/?node=References+quick+reference.
When you have ugly data structures like this, make an interface for it so your life is easier:
foreach my $fact ( $data_obj->facts ) { # make some lightweight class for this
....;
}
Even without that, consider using a reference to just the part of the data structure you need so you don't think about the rest:
my $facts = $deconstructed->{data}{workspaces}[0]{workspace}{facts};
foreach my $fact ( #$facts ) {
print "Thing is $fact->{code}\n";
}
It's just a reference, so you're not recreating anything. Since you only have to think about the parts beyond the facts key, the problem doesn't look as hard.

How can I create multidimensional arrays in Perl?

I am a bit new to Perl, but here is what I want to do:
my #array2d;
while(<FILE>){
push(#array2d[$i], $_);
}
It doesn't compile since #array2d[$i] is not an array but a scalar value.
How should I declare #array2d as an array of array?
Of course, I have no idea of how many rows I have.
To make an array of arrays, or more accurately an array of arrayrefs, try something like this:
my #array = ();
foreach my $i ( 0 .. 10 ) {
foreach my $j ( 0 .. 10 ) {
push #{ $array[$i] }, $j;
}
}
It pushes the value onto a dereferenced arrayref for you. You should be able to access an entry like this:
print $array[3][2];
Change your "push" line to this:
push(#{$array2d[$i]}, $_);
You are basically making $array2d[$i] an array by surrounding it by the #{}... You are then able to push elements onto this array of array references.
Have a look at perlref and perldsc to see how to make nested data structures, like arrays of arrays and hashes of hashes. Very useful stuff when you're doing Perl.
There's really no difference between what you wrote and this:
#{$array2d[$i]} = <FILE>;
I can only assume you're iterating through files.
To avoid keeping track of a counter, you could do this:
...
push #array2d, [ <FILE> ];
...
That says 1) create a reference to an empty array, 2) storing all lines in FILE, 3) push it onto #array2d.
Another simple way is to use a hash table and use the two array indices to make a hash key:
$two_dimensional_array{"$i $j"} = $val;
If you're just trying to store a file in an array you can also do this:
fopen(FILE,"<somefile.txt");
#array = <FILE>;
close (FILE);