How can I access an Array within a Hash? [closed] - arrays

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I am building an installer for perl modules we require at work. After all of the dependencies are installed, I need to check if the module is working properly "use This::Module". The problem is, all of the modules are being installed within a certain order.
The hash looks like...
my %modules=(
0 => {'name' => '/root/mods/CGI/perl-FCGI-0.74-8.amzn2.0.2.x86_64.rpm', 'method' => 'rpm', 'status'=>'pending'},
1 => {'name' => '/root/mods/CGI/perl-CGI-3.63-4.amzn2.noarch.rpm', 'method' => 'rpm','status'=>'done', 'validate' => ['CGI','CGI::Carp']},
2 => {'name' => '/root/mods/Digest/perl-Digest-1.17-245.amzn2.noarch.rpm', 'method' => 'rpm','status'=>'pending'},
3 => {'name' => '/root/mods/Digest/perl-Digest-MD5-2.52-3.amzn2.0.2.x86_64.rpm', 'method' => 'rpm','status'=>'done', 'validate' => ['Digest::MD5']},
4 => {'name' => '/root/mods/HTTP/perl-Business-ISBN-Data-20120719.001-2.el7.noarch.rpm','method' => 'rpm','status'=>'pending'},
5 => {'name' => '/root/mods/HTTP/perl-Data-Dumper-2.145-3.el7.x86_64.rpm','method' => 'rpm','status'=>'pending'},
6 => {'name' => '/root/mods/HTTP/perl-Business-ISBN-2.06-2.el7.noarch.rpm','method' => 'rpm','status'=>'done'}, 'validate' => ['HTTP::Request::Common']},
Each newline is the start of a new module. Once one the 'status' => 'done' I need to access the modules within 'validate'. This is an array because there are cases where there are multiple modules tied to one install sequence.
How can I loop through and return each array element by itself?

'validate' => {['CGI','CGI::Carp']}},
You don't have arrays.
The value of validate is between { and } so it is a hashref.
The arrayref is the first entry in the hash, so it gets converted to a string to be used as a key.
You end up with something like:
{
'name' => '/root/mods/CGI/perl-CGI-3.63-4.amzn2.noarch.rpm',
'method' => 'rpm',
'status' => 'done',
'validate' => {
'ARRAY(0x7f9ab601c4e0)' => undef
}
};
Make sure you use strict; and use warnings;. It would have alerted you to this:
Odd number of elements in anonymous hash at Untitled.pl line 9.
You need to fix your data structure. If you want an array, then put it in an array.
#!/usr/bin/perl
use strict;
use warnings;
use v5.10;
use Data::Dumper;
my %modules = (
0 => {
'name' => '/root/mods/CGI/perl-FCGI-0.74-8.amzn2.0.2.x86_64.rpm',
'method' => 'rpm',
'status' => 'pending'
},
1 => {
'name' => '/root/mods/CGI/perl-CGI-3.63-4.amzn2.noarch.rpm',
'method' => 'rpm',
'status' => 'done',
'validate' => [ 'CGI', 'CGI::Carp' ]
},
);
Then you can access the arrayref:
my $arrayref = $modules{1}->{validate};
and loop over it:
foreach my $value (#$arrayref) {
say $value
}

Related

Array element validation doesn't pass even when it should

I have a trouble validating an array members in validation for Laravel. For array itself it passes, but for elements themselves, it fails.
Open json in console, shows structure of data being sent. It's clearly a integer. Since it's associative array, not sure how it even finds it's value as show in error handling red rectangle on the bottom of the page.
Here is my validation logic:
$validation = Validator::make(
$request->all(),
[
'load_place' => 'required|max:255',
"unload_place" => 'required|max:255',
"comment" => 'required|max:255',
'time_in' => 'required',
'time_out' => 'required',
"vehicles" => 'required|array',
"vehicles.*" => "required|integer",
'operator_id' => 'required|integer',
'sec_id' => 'required|integer'
]
);
And here is how it's returned:
if($validation->fails()){
$response = array(
"message" => "Failed",
"errors" => $errors,
"test" => $request->vehicles[0]
);
return response()->json($response);
}
That request[0], is that number at the bottom.
Edit1:
Keys in that marked array, are set on frontend, they are not not predefined. They can be whatever.
Change "vehicles.*" => "required|integer", to "vehicles.*.vehicle_id" => "required|integer", and it should work.
Keys is set on frontend, they are not not predefined. That what i am trying to say.
Try to replace "vehicles.*" => "required|integer", with new Rule::forEach rule for nested array data - guess it should work.
"vehicles.*" => Rule::forEach(function($value, $attribute) {
return [
Rule::integer()->min(1) //min(1) as eg if it's for an id field which cannot be 0
];
}),

Easiest way to grab "target" key from the hash shown [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 2 years ago.
Improve this question
This is the output of Dumper for the hashref in question:
#!/usr/bin/perl
use Data::Dumper;
sub getUpgradeTaskUUIDS {
my $derp = SF::Transaction::Update::getUpgradeTasks();
print "Derp is:\n";
print Dumper $derp;
[... do stuff ...]
}
The following hashref is received by another function. task_readiness may have elements, it may not. I managed to grab the "target" => '_6f5c8c84-6251-11eb-8def-fd627969bf5f_52dcea68-60e9-11eb-830e-f71d7dc3a91f' in some convoluted way, but I am wondering what the cleanest, simplest way would be? I need to be able to grab target -> '' values from both task_readiness and task_upgrade as well if both have applicable elements:
Derp is:
$VAR1 = {
'tasks_readiness' => [],
'tasks_upgrade' => [
{
'type' => 6,
'hidden' => 0,
'state_name' => '1',
'allow_html_in_msg' => 1,
'aq_id' => '0e43ed66-663e-11eb-a97b-b72c0f665ee4',
'subtype_name' => '',
'retry_type' => 1,
'safe_to_delete' => 1,
'create_time' => 1612370227,
'delay_run' => 1612370299,
'last_state_change' => 1612370287,
'description' => 'Apply Upgrade 7.0.0-1242 to Devices',
'subtype' => 14,
'group_name' => 'DEVICE_UPGRADE',
'name' => '',
'type_name' => '6',
'retries' => 0,
'state' => 1,
'target' => '_6f5c8c84-6251-11eb-8def-fd627969bf5f_52dcea68-60e9-11eb-830e-f71d7dc3a91f',
'domain' => 'e276abec-e0f2-11e3-8169-6d9ed49b625f',
'cost' => 10,
'pid' => 0,
'message' => '<p><strong>Failed to update 2 devices.<br></strong></p><p><strong>Please reapply policies to your managed devices.</strong></p>',
'user' => 'admin'
}
]
};
The easiest way to get the value you want would probably be:
$derp->{tasks_upgrade}[0]{target}
And increment that 0 if you have other entries in the array.
Note: Thanks to Jim Garrison for pointing out my earlier idiocy.

Get the hash number

I am fairly new in Perl, and having worked all my life with R, there are something that I can't really can wrap my mind around.
I have an array of hashes. In all of the hashes, the keys are the same ones, but the values are different. I want to get the number of the hash that has a specific value in it, because in that hash there is another value that I want (and varies among different samples).
I don't know if this is the way that I should be addressing it, but is the one I can think of. Here is a piece of the array:
$VAR16 = {
'harmonized_name' => 'geo_loc_name',
'attribute_name' => 'geo_loc_name',
'content' => 'not determined',
'display_name' => 'geographic location'}
$VAR17 = {
'harmonized_name' => 'env_package',
'attribute_name' => 'env_package',
'content' => 'missing',
'display_name' => 'environmental package'}
In this example, I would want the 'content' value of the hash that has 'harmonized_name' = env_package
You can use grep to filter all array elements which have 'harmonized_name' = env_package, and then check their values for content,
use strict;
use warnings;
my #AoH = (
{
'harmonized_name' => 'geo_loc_name',
'attribute_name' => 'geo_loc_name',
'content' => 'not determined',
'display_name' => 'geographic location'
},
{
'harmonized_name' => 'env_package',
'attribute_name' => 'env_package',
'content' => 'missing',
'display_name' => 'environmental package'
}
);
my #result = grep { $_->{harmonized_name} eq "env_package" } #AoH;
print $_->{content}, "\n" for #result;
output
missing

CodeIgniter + NuSOAP - Input multidimensional array

I was looking for it several times but didn't find any answer that help me, so I'm asking now and I hope someone can help me.
I have some webservices in a CodeIgniter application that returns complex types and whatever, and now I need create a service that RECEIVE a complex type like this:
Array ("position1" => 'mambo jambo',
"position2" => 'more mambo jambo',
"position3" => Array("0" => Array(), "1" => Array()),
"position4" => Array("0" => Array(), "1" => Array());
In resume, it a complex type that have some normal data and inside it two arrays that receive N positions of another array. I need it because I receive some Invoice and in invoice I receive N products (every with about 4 positions) and N quotas of payment (every with value, date, etc).
I tryed create a complex type with two positions where every of them as an other complex type that is an array of another complex type. Yes, I know, it is complex =P
Is like this that I use when I create output services to return data like this, but to input doesn't works. When I try test it in SoapUI App that generate this XML:
<soapenv:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:urn="urn:SOAPServerWSDL">
<soapenv:Header/>
<soapenv:Body>
<urn:gravaNotaFiscal soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<token xsi:type="xsd:string">?</token>
<nota_fiscal xsi:type="ped:NotaFiscal" xmlns:ped="http://ultraman/tr1/sistema/api/pedidoservice?wsdl">
<!--You may enter the following 7 items in any order-->
<filial xsi:type="xsd:string">?</filial>
<numero xsi:type="xsd:string">?</numero>
<serie xsi:type="xsd:string">?</serie>
<dt_emissao xsi:type="xsd:string">?</dt_emissao>
<valor xsi:type="xsd:string">?</valor>
<itens_nota xsi:type="ped:Itens_Nota"/>
<duplicatas_nota xsi:type="ped:Duplicatas_Nota"/>
</nota_fiscal>
</urn:gravaNotaFiscal>
</soapenv:Body>
</soapenv:Envelope>
Last two positions "itens_nota" and "duplicatas_nota" need to be my two arrays, but SoapUI doesn't create it right.
Using "itens_nota" for example, I created two complex types like this:
$this->nusoap_server->wsdl->addComplexType(
'ItemNF',
'complexType',
'struct',
'all',
'',
array(
"filial" => array('name' => 'filial', 'type' => 'xsd:string'),
"serie" => array('name' => 'serie', 'type' => 'xsd:string'),
"nota_fiscal" => array('name' => 'nota_fiscal', 'type' => 'xsd:string'),
"seq" => array('name' => 'seq', 'type' => 'xsd:string'),
"pedido" => array('name' => 'pedido', 'type' => 'xsd:string'),
"item" => array('name' => 'item', 'type' => 'xsd:string'),
"qtd" => array('name' => 'qtd', 'type' => 'xsd:string')
)
);
$this->nusoap_server->wsdl->addComplexType("Itens_Nota",
"complexType",
"array",
"",
"SOAP-ENC:Array",
array(),
array(array("ref"=>"SOAP-ENC:arrayType","wsdl:arrayType"=>"tns:ArrayOfString[]")),
"tns:ItemNF"
);
My input parameter is "Nota_Fiscal", is a complex type and it last two positions is:
"itens_nota" => array("name" => 'itens_nota', 'type' => 'tns:Itens_Nota'),
"duplicatas_nota" => array("name" => 'duplicatas_nota', 'type' =>'tns:Duplicatas_Nota')
My arrays!
But doesn't works! Someone know why? Where I made mistakes?
If possible I wanna an example of how make a service to input arrays like this, doesn't need be my problem, only an example to give me a direction.
Thanks!

Perl- Iterating through an array of hashes with square brackets

I have a hash whose keys is a string and key is array(the complication is that the array is defined in the square bracket), So my hash is like this..
model = {
'add' => [
{'name' => 'abc1', 'value' => 'def' },
{'name' => 'abc2', value => 'ghi'}
],
'remove' => [
{'name' => 'abc1', 'value' => 'def' },
{'name' => 'abc2', value => 'ghi'}
]
};
So what I am trying to achive is that when I try to iterate through the hashes of array
model->{add} as
print $_->{name} foreach(model->{add})
it doesnt work.
I guess this is because the array is in [] instead of ().
Considering the input cannot be changed. please let me know how to get through this...
$model = { 'add' => [ {'name' => 'abc1', 'value' => 'def' },
{'name' => 'abc2', 'value' => 'ghi'} ],
'remove' => [ {'name' => 'abc1', 'value' => 'def' },
{'name' => 'abc2', 'value' => 'ghi'} ] };
print $_->{name} foreach( #{ $model->{add} } );
You have a 3-level nested structure: A HashRef containing ArrayRefs containing HashRefs.
my $model = {
'add' => [
{
'name' => 'abc1',
'value' => 'def'
}, {
'name' => 'abc2',
value => 'ghi'
}
],
'remove' => [
{
'name' => 'abc1',
'value' => 'def'
}, {
'name' => 'abc2',
value => 'ghi'
}
]
};
To access those nested arrays and hashes, you need to dereference them, by adding % or # in front of it, depending on whether it is a hash or array.
my $arrayref = $model->{add};
foreach my $hashref (#$arrayref) {
print $hashref->{name}, "\n";
}
The statement:
print $_->{name} foreach(model->{add})
Does not work because model is a bareword, not a variable. If you have these two pragmas in your code:
use strict;
use warnings;
You will not be able to make mistakes like this. warnings will tell you:
Unquoted string "model" may clash with future reserved word at ...
Name "main::model" used only once: possible typo at ...
Use of uninitialized value in print at ...
And strict will tell you:
Can't use bareword ("model") as a HASH ref while "strict refs" in use at ...
However, if you do not have those two pragmas enabled, Perl will happily print the empty string and be silent about the whole thing. Which makes the mistake rather hard to detect.
The correct way to handle this is to grab the correct scalar value from the hash, and dereference it using the correct sigil. If you look at the key 'add':
'add' => [
You'll see that it has an array reference stored in it, which means the sigil to use is #. You'll need support curly braces to disambiguate the references. Also, you have to refer to your variable as $model.
print $_->{name} for #{ $model->{add} };
Which is the same as
my $adds = $model->{add};
print $_->{name} for #$adds;
First and foremost use use strict; use warnings;
The scalar model should be written as
my $model = { 'add' => [ {'name' => 'abc1', 'value' => 'def' }, {'name' => 'abc2', value => 'ghi'} ], 'remove' => [ {'name' => 'abc1', 'value' => 'def' }, {'name' => 'abc2', value => 'ghi'} ] };
and
print $_->{name} foreach( ( #{ $model->{ add } } ) );

Resources