Perl -- unable to construct array of objects - arrays

I've tried two similar bits of syntax. This first one works:
my $obj = PI::something::ObjectManipulator->new();
$obj->setValue('HELLO');
my $objList = [$object];
This, however, doesn't:
my $objList= [];
foreach my $value (#values) {
my $obj = PI::something::ObjectManipulator->new();
$obj->setValue($value);
push #$objList, $obj;
};
What is the difference between these two way of doing things? Why doesn't the second work? (By not work, it seems to be that $objList is still empty at the end of the code.)

Assuming my $objList = [$object]; is a typo for my $objList = [$obj];, and assuming, my #values = 'HELLO';, there are no differences.
Assuming you meant "#$objList is still empty" when you said "$objList is still empty", that can only happen if the loop isn't entered (i.e. #values is empty).

Related

Directly access nested JSON data in perl?

I'm not familiar with hash/reference syntax with Perl and it makes my eyes hurt trying.
I have the following JSON:
{
"Arg":"Custom_Light state alias protocol",
"Results": [
{
"Name":"Custom_Light",
"Internals": { },
"Readings": {
"protocol": { "Value":"V3", "Time":"2017-01-14 18:49:18" },
"state": { "Value":"off", "Time":"2017-03-05 10:39:50" }
},
"Attributes": { "alias": "Kitchen light" }
} ],
"totalResultsReturned":1
}
How do I directly get the Reading > Protocol Value and Reading > state Value as well as the Attributes > Alias?
I am using the default JSON encoder/decoder and it works splendid. Using Dumper($json) I get all the JSON, but I have no clue how to directly access it without using foreach with all the arrays within arrays in this.
I have tried the following:
my $json = from_json( $readout, { utf8 => 1 } );
print "No. Entries:", scalar(keys($json)); #works, returns 3
my #results = %$json{Results};
Dumper(#results[1]); #I get the Results array
From here it already is ugly. What's that %$ doing there? I thought I could do something like print ${ $json->{'Results'}->[1] }{'Readings'}; but that leads me nowhere.
Give me wisdom. How do I access the Protocol value directly? How do I access the state value directly? And finally, how to get to the alias Attribute?
I don't know what I'm doing but I'm getting somewhere with my $test = %{${%$json{Results}}[0]}{Name}; #I get "Custom_Light", nice. Is this the way to go with a gazillion of weird % and $ just randomly thrown in?
You want
$json->{Results}[0]{Readings}{protocol}{Value}
$json->{Results}[0]{Readings}{state}{Value}
$json->{Results}[0]{Attributes}{alias}
However, since the Results item is an array, you are likely to want to iterate over all of its elements, although in this case there is only one element
I find it useful to extract one level of reference at a time into temporary variables. It would look like this
my $results = $json->{Results};
for my $result ( #$results ) {
my $readings = $result->{Readings};
my $attributes = $result->{Attributes};
printf "Protocol: %s\n", $readings->{protocol}{Value};
printf "State: %s\n", $readings->{state}{Value};
printf "Alias: %s\n", $attributes->{alias};
print "\n";
}
Have a look at perlreftut, perldsc, and perlref, it will help you understand how to access deeply nested structures in Perl.
print "No. Entries:", scalar(keys($json)); #works, returns 3
Actually, this will no longer work. Using keys on a scalar, was an experimental feature added in Perl 5.14 that allowed each, keys, push, pop, shift, splice, unshift, and values to be called with a scalar argument. This experiment was considered unsuccessful, and was removed in 5.23. See also Experimental values on scalar is now forbidden. So, you should dereference the hash reference $json before applying keys:
print "No. Entries:", scalar keys %$json;
As described in perlref, %$ref dereferences the hash reference $ref. Next, lets look at this line:
my #results = %$json{Results};
This actually first creates a new (anonymous) hash ( Result => $json->{Result} ) and then assigns this to #results making #result = ( 'Result', $json->{Result} ). So that is why you now can refer to $json->{Result}[0] as $result[1].
But this is obscure coding, and probably not intended as well. So to return to your question, to get the Value field you could write:
my $value = $json->{Results}[0]{Readings}{state}{Value};
And to get the alias field:
my $alias = $json->{Results}[0]{Attributes}{alias};

php calling a string in an array creates empty array?

Currently I have this:
<?php
$fn = "file.txt";
$file = file_get_contents("./$fn");
$array = array($file);
?>
An example of whats in the text file:
array(1,4,3,2),array(3,2,1,2),array(5,6,7,8)
However when I print the array or even sizeof($array) it is empty. Whats the deal?
The content of your file is plain text not array data structures. You'll have to parse the content yourself. Here is one way of doing it:
$file_content = "array(1,4,3,2),array(3,2,1,2),array(5,6,7,8)";
$matches = [];
$arrays = [];
if (preg_match_all('~array\(((?:(?:\d+),?)*)\),?~', $file_content, $matches)) {
$arrays = array_map(function ($array) { return explode(',', $array); }, $matches[1]);
}
$arrays now contains arrays as you would expect and you can use count() to check their size.
If you know that your file always contain arrays another way to do it is by using eval.
Another approach
eval('$arrays2 = [' . $file_content . '];');
Now $arrays2 contains the same arrays. There is one subtle difference. The former approach does not cast the values to integers whereas eval does.
Warning: Only use eval() if are 100% sure that you know what goes into the function. Also note that this approach will fail on bad data, whereas the former is a little more resilient.

Associative array - PERL

I need to know the way of creating the Associative array in Perl.
Basically now I have the code which is implemented as follows:
my $getEmployeeListOfTeamQuery = "SELECT profiles.userid
FROM user_group_map,profiles
WHERE user_group_map.group_id = $teamId
AND profiles.userid = user_group_map.user_id
AND profiles.active = 'y'
AND profiles.login_name NOT LIKE 'qa_%'
AND profiles.disabledtext = ''
GROUP BY profiles.login_name
ORDER BY profiles.login_name";
my $getEmployeeListOfTeam = $dbh->prepare($getEmployeeListOfTeamQuery);
$getEmployeeListOfTeam -> execute();
my #techs = ();
while(my ($tech) - $getEmployeeListOfTeam->fetchrow_array) {
push #techs,$tech;
}
So above code will be having the query in $getEmployeeListOfTeamQuery, Created the array names as techs.
Then tried pushing the values in to the the array.
Here it is working fine.
My question here is regarding the creation of associative array.
That is I need to query as follows : "SELECT profiles.userid, profiles,username....."
Hence I need to create a Associative array with "userid" as key and "username" as value.
I worry about the resources that you are using to learn Perl. Perl programmers haven't used the term "associative array" since Perl 5 was released over twenty years ago. We now call these structures "hashes". If you're learning from resources that use the term "associative array", then they are almost certainly horribly outdated.
But, to answer your question. The code is pretty simple.
my $sql = 'select profiles.userid, profiles.username...';
my $sth = $dbh->prepare($sql);
$sth->execute;
my %techs_hash;
while (my #row = $sth->fetchrow_array) {
$techs_hash{$row[0]} = $row[1];
}
Use selectcol_arrayref() and the Columns attribute:
my $aref = $dbh->selectcol_arrayref('select userid, login_name ...', {Columns => [1, 2]});
my %hash = #$aref;
you can fetch all rows into hash of hashes by one call to selectall_hashref:
my $tech=$dbh->selectall_hashref("select profile.userid, profiles.username, ...",'userid');
or you can fetch all rows into array of hashes with selectall_arrayref with attribute {Slice=>{}} :
my $tech=$dbh->selectall_arrayref("select profile.userid, profiles.username, ...",{Slice=>{}});
and then turn it into desired hash (this is exactly what you want):
my $result;
$result->{$_->{userid}}=$_->{username} foreach #$tech;
my #l;
while(my $h = $sth->fetchrow_hashref){
push #l,$h;
}
my %hash;
map { $hash{$_->{userid}} = $_->{username} } #l;

Perl - Search array of words to check for a partial match in any part of an email address

Again, a whole day and I am stuck again.
I need to use an array of words or var that contains forbidden words that cannot appear in an email address.
Either:
$baddies = 'smtp mailer sysop';
or
#baddies = qw(smtp mailer sysop);
or
#baddies = qw/smtp mailer sysop/;
There are more bad words in the array too, about two dozen.
I am not running the latest version of perl so ~~ and so on are not supported.
I have a loop going on that sends the bands schedule out.
In that loop I need to check to see if the email contains any of those words.
I realize there may be some good emails that contain a match but, that is fine.
I have tried literally dozens of examples after I gave up trying to figure it out.
Latest was:
####FYI## $uaddress is from the foreach $uaddress(#addresses){ loop.
my %params = map { $uaddress => 1 } #baddies;
if(exists($params{$uaddress})) {
print "yep, it's there"; #for testing
push(#failed,"$uaddress is restricted<br />");
But, everything I tried just does not do what I need.
I even tried =~ and so on.
I AM REALLY feeling stupid about now..
I need another lesson here folks.. Thanks in advance.
Update: I also tried:
$baddies = 'smtp mailer sysop';
my #baddies = split / /, $baddies;
# iterate through the array
foreach (#baddies) {
if($_ =~ $uaddress) #I also reversed that {
print qq~$uaddress contains $_~;
}
}
Through trial, error and dumb luck, I haphazardly got this below to work:
foreach $uaddress(#addressList) {
$uaddress =~ s/\s//g;
#baddies = qw(smtp mailer sysop);
my #failed;
foreach (#baddies) {
if($uaddress =~ m/$_/i) {
push(#failed,"$uaddress is restricted because it found \"$_\" in the address<br />");
}
}
##stuff happens with emails that passed like Email::Verify
}

Why do I get the same value from iterating over this hash?

I'm trying to put a hash %listvol into an array #fileInfo in Perl.
#fileInfo = ($filename, $data, $index, \%listvol);
%listvol contains a list of volume: key = $vol, value = $vol.
The first $vol values are ABCDEF, then GFFFF, EEEAA - always different.
Then I put the array #fileInfo in the hash %listeAllFile:
$listeAllFile{$nameOfFile} = [#fileInfo];
Later I'm trying to get the hash %listvol without success. I'm using this code:
foreach $key (keys %listeAllFile) {
#tab = #{ $listeAllFile{$key} };
$filename = $tab[0];
%listvol = %{ $tab[3] };
foreach $vol (keys %listvol) {
print "\n vol is $vol for file $filename";
}
The file name is always different, so it is ok. But the value of the variable $vol is always the same, ABCDEF. It seems that I get get each time the same value.
Does anyone have an idea?
While you didn't include code to reproduce your problem, I'm fairly sure that the issue is that you're storing a reference to the same %listvol hash in each array.
When you change the contents of %listvol for the second entry, you're modifying the first entry at the same time. One way to fix that is to use {%listvol} instead of \%listvol. The former makes a shallow copy of the current contents of %listvol, just like [#fileInfo] makes a shallow copy of the current contents of #fileInfo.

Resources