Access perl attribute in associative array - arrays

Is there an easier way to access the value of the 'type' attribute without looping through the whole object to find it?
[
{ type => "voipPassword", vals => ["data"] },
{ type => "sn", vals => ["data"] },
{ type => "voipExtension", vals => [data] },
{ type => "cn", vals => ["data"] },
{ type => "telephoneNumber", vals => [data] },
{ type => "objectClass", vals => ["data"] },
{ type => "phoneMAC", vals => ["data"] },
]

You can access type directly like this example:
#!/usr/bin/perl
use strict;
use warnings;
my $ref = [
{ type => "voipPassword", vals => ["data"] },
{ type => "sn", vals => ["data"] },
{ type => "voipExtension", vals => ["data"] },
{ type => "cn", vals => ["data"] },
{ type => "telephoneNumber", vals => ["data"] },
{ type => "objectClass", vals => ["data"] },
{ type => "phoneMAC", vals => ["data"] },
];
print $ref->[0]->{'type'} . "\n";
print $ref->[1]{'type'} . "\n";
Output:
voipPassword
sn
See perlreftut for more details.

Related

Perl generating hash of complex records

The big problem that I can't seem to figure out.
I need to input into this complex hash (array?):
my $raterequest =
{
Shipment =>
{
Shipper =>
{
(static data here)
},
ShipTo =>
{
(static data here too)
},
Package =>
[
{
PackagingType =>
{
Code => '02',
Description => 'Package'
},
PackageWeight =>
{
UnitOfMeasurement =>
{
Code => 'LBS'
},
Weight => $boxWt
},
},
{
PackagingType =>
{
Code => '02',
Description => 'Package'
},
PackageWeight =>
{
UnitOfMeasurement =>
{
Code => 'LBS'
},
Weight => $boxWt
},
}
],
}
};
What I need to input is everything inside the Package array.
I have an LoH that generates an output like this:
my %carton_specs =
(
25 => {
boxQty => 25,
boxWt => 4,
boxNo => 2
},
50 => {
boxQty => 50,
boxWt => 8,
boxNo => 17
},
);
Where I need to repeat the anonymous array inside Package
{
PackagingType =>
{
Code => '02',
Description => 'Package'
},
PackageWeight =>
{
UnitOfMeasurement =>
{
Code => 'LBS'
},
Weight => $boxWt
},
},
times the number returned from $boxNo. The only variable that changes in that is the Weight => $boxWt
Please excuse anything that I might have named wrong. I have been fighting with this for 2 days and my head is exploding.
It sounds to me like you are looking for push plus the information from perlreftut (plus maybe the .. range operator). I hope I understood your specifications correctly:
use warnings;
use strict;
use Data::Dump;
my $raterequest = {
Shipment => {
Package => [ ],
} };
my %carton_specs = (
25 => { boxQty => 25, boxWt => 4, boxNo => 2 },
50 => { boxQty => 50, boxWt => 8, boxNo => 17 },
);
for my $carton (sort keys %carton_specs) {
for ( 1 .. $carton_specs{$carton}{boxNo} ) {
push #{ $raterequest->{Shipment}{Package} }, {
PackagingType => {
Code => '02',
Description => 'Package',
},
PackageWeight => {
UnitOfMeasurement => { Code => 'LBS' },
Weight => $carton_specs{$carton}{boxWt},
},
};
}
}
dd $raterequest;
Output:
{
Shipment => {
Package => [
{
PackageWeight => { UnitOfMeasurement => { Code => "LBS" }, Weight => 4 },
PackagingType => { Code => "02", Description => "Package" },
},
{
PackageWeight => { UnitOfMeasurement => { Code => "LBS" }, Weight => 4 },
PackagingType => { Code => "02", Description => "Package" },
},
{
PackageWeight => { UnitOfMeasurement => { Code => "LBS" }, Weight => 8 },
PackagingType => { Code => "02", Description => "Package" },
},
# ... omit 16 repetitions of the previous hashref ...
],
},
}

Perl: Accessing and handling objects in an array

I try to handle the following Array which was generated by get_pool_member_object_status_($pool)
from http://search.cpan.org/~ltp/BigIP-iControl/lib/BigIP/iControl.pm#get_pool_member_object_status_($pool)
$VAR1 = [
[
bless( [
bless( {
'member' => bless( {
'address' => '192.168.100.141',
'port' => '80'
}, 'Common::IPPortDefinition' ),
'object_status' => bless( {
'availability_status' => 'AVAILABILITY_STATUS_GREEN',
'status_description' => 'Pool member is available',
'enabled_status' => 'ENABLED_STATUS_ENABLED'
}, 'LocalLB::ObjectStatus' )
}, 'LocalLB::PoolMember::MemberObjectStatus' ),
bless( {
'member' => bless( {
'address' => '192.168.100.142',
'port' => '80'
}, 'Common::IPPortDefinition' ),
'object_status' => bless( {
'availability_status' => 'AVAILABILITY_STATUS_GREEN',
'status_description' => 'Pool member is available',
'enabled_status' => 'ENABLED_STATUS_ENABLED'
}, 'LocalLB::ObjectStatus' )
}, 'LocalLB::PoolMember::MemberObjectStatus' ),
bless( {
'member' => bless( {
'address' => '192.168.100.143',
'port' => '80'
}, 'Common::IPPortDefinition' ),
'object_status' => bless( {
'availability_status' => 'AVAILABILITY_STATUS_GREEN',
'status_description' => 'Pool member is available',
'enabled_status' => 'ENABLED_STATUS_ENABLED'
}, 'LocalLB::ObjectStatus' )
}, 'LocalLB::PoolMember::MemberObjectStatus' ),
bless( {
'member' => bless( {
'address' => '192.168.100.144',
'port' => '80'
}, 'Common::IPPortDefinition' ),
'object_status' => bless( {
'availability_status' => 'AVAILABILITY_STATUS_GREEN',
'status_description' => 'Pool member is available',
'enabled_status' => 'ENABLED_STATUS_ENABLED'
}, 'LocalLB::ObjectStatus' )
}, 'LocalLB::PoolMember::MemberObjectStatus' )
], 'LocalLB::PoolMember::MemberObjectStatus[]' )
]
];
I couldn't figure out how this should work. I tried several examples from perldsc. The examples there mostly concern ARRAYS OF HASHES. But the above array is...? I don't even know what kind of array this is. Can someone point me in the right direction?
So for example how do I access the "object_status"->"availability_status" of a "member"->"address"
Thx simbabque. This is the output I get from Data::Printer:
[
[0] [
[0] LocalLB::PoolMember::MemberObjectStatus[] {
public methods (0)
private methods (0)
internals: [
[0] LocalLB::PoolMember::MemberObjectStatus,
[1] LocalLB::PoolMember::MemberObjectStatus,
[2] LocalLB::PoolMember::MemberObjectStatus,
[3] LocalLB::PoolMember::MemberObjectStatus
]
}
]
]
So you are trying to access the 'availability_status' and 'address'
I didn't traverse this whole object but with this code I am able to print the required fields.
#!/usr/bin/perl -w
use strict;
use warnings;
use Data::Dumper;
my $obj = [
[
bless( [
bless( {
'member' => bless( {
'address' => '192.168.100.141',
'port' => '80'
}, 'Common::IPPortDefinition' ),
'object_status' => bless( {
'availability_status' => 'AVAILABILITY_STATUS_GREEN',
'status_description' => 'Pool member is available',
'enabled_status' => 'ENABLED_STATUS_ENABLED'
}, 'LocalLB::ObjectStatus' )
}, 'LocalLB::PoolMember::MemberObjectStatus' ),
bless( {
'member' => bless( {
'address' => '192.168.100.142',
'port' => '80'
}, 'Common::IPPortDefinition' ),
'object_status' => bless( {
'availability_status' => 'AVAILABILITY_STATUS_GREEN',
'status_description' => 'Pool member is available',
'enabled_status' => 'ENABLED_STATUS_ENABLED'
}, 'LocalLB::ObjectStatus' )
}, 'LocalLB::PoolMember::MemberObjectStatus' ),
bless( {
'member' => bless( {
'address' => '192.168.100.143',
'port' => '80'
}, 'Common::IPPortDefinition' ),
'object_status' => bless( {
'availability_status' => 'AVAILABILITY_STATUS_GREEN',
'status_description' => 'Pool member is available',
'enabled_status' => 'ENABLED_STATUS_ENABLED'
}, 'LocalLB::ObjectStatus' )
}, 'LocalLB::PoolMember::MemberObjectStatus' ),
bless( {
'member' => bless( {
'address' => '192.168.100.144',
'port' => '80'
}, 'Common::IPPortDefinition' ),
'object_status' => bless( {
'availability_status' => 'AVAILABILITY_STATUS_GREEN',
'status_description' => 'Pool member is available',
'enabled_status' => 'ENABLED_STATUS_ENABLED'
}, 'LocalLB::ObjectStatus' )
}, 'LocalLB::PoolMember::MemberObjectStatus' )
], 'LocalLB::PoolMember::MemberObjectStatus[]' )
]
];
print Dumper($obj->[0]->[0]->[0]->{member}->{address});
print Dumper($obj->[0]->[0]->[0]->{object_status}->{availability_status});
print Dumper($obj->[0]->[0]->[1]->{member}->{address});
print Dumper($obj->[0]->[0]->[1]->{object_status}->{availability_status});
print Dumper($obj->[0]->[0]->[2]->{member}->{address});
print Dumper($obj->[0]->[0]->[2]->{object_status}->{availability_status});
print Dumper($obj->[0]->[0]->[3]->{member}->{address});
print Dumper($obj->[0]->[0]->[3]->{object_status}->{availability_status});
Output:
$VAR1 = '192.168.100.141';
$VAR1 = 'AVAILABILITY_STATUS_GREEN';
$VAR1 = '192.168.100.142';
$VAR1 = 'AVAILABILITY_STATUS_GREEN';
$VAR1 = '192.168.100.143';
$VAR1 = 'AVAILABILITY_STATUS_GREEN';
$VAR1 = '192.168.100.144';
$VAR1 = 'AVAILABILITY_STATUS_GREEN';
Hope this helps and now you should be able to traverse this data structure with loops.

Using Yii2 with array of data and a Gridview with sorting and filter

I've an array
$resultData = [
array("id"=>1,"name"=>"Cyrus","email"=>"risus#consequatdolorvitae.org"),
array("id"=>2,"name"=>"Justin","email"=>"ac.facilisis.facilisis#at.ca"),
array("id"=>3,"name"=>"Mason","email"=>"in.cursus.et#arcuacorci.ca"),
array("id"=>4,"name"=>"Fulton","email"=>"a#faucibusorciluctus.edu"),
array("id"=>5,"name"=>"Neville","email"=>"eleifend#consequatlectus.com"),
array("id"=>6,"name"=>"Jasper","email"=>"lectus.justo#miAliquam.com"),
array("id"=>7,"name"=>"Neville","email"=>"Morbi.non.sapien#dapibusquam.org"),
array("id"=>8,"name"=>"Neville","email"=>"condimentum.eget#egestas.edu"),
array("id"=>9,"name"=>"Ronan","email"=>"orci.adipiscing#interdumligulaeu.com"),
array("id"=>10,"name"=>"Raphael","email"=>"nec.tempus#commodohendrerit.co.uk"),
];
A dataprovider :
$dataProvider = new ArrayDataProvider([
'key'=>'id',
'allModels' => $resultData,
'sort' => [
'attributes' => ['id', 'name', 'email'],
],
]);
And the Gridview :
echo GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
[
'attribute' => 'name',
'value' => 'name',
],
[
"attribute" => "email",
'value' => 'email',
]
]
]);
As is, the code make me View the array in a grid, and the possibility to sort it when clicking on columns. That's ok.
But how to do to use filtering ?
I tried with the following :
$searchModel = ['id' => null, 'name' => '', 'email' => ''];
echo GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
[
'attribute' => 'name',
'value' => 'name',
],
[
"attribute" => "email",
'filter' => '<input class="form-control" name="filteremail" value="da" type="text">',
'value' => 'email',
]
]
]);
But it's not working.
Does I have to filter myself the object depending on the $get value ?
My solution with full code :
$resultData = [
array("id"=>1,"name"=>"Cyrus","email"=>"risus#consequatdolorvitae.org"),
array("id"=>2,"name"=>"Justin","email"=>"ac.facilisis.facilisis#at.ca"),
array("id"=>3,"name"=>"Mason","email"=>"in.cursus.et#arcuacorci.ca"),
array("id"=>4,"name"=>"Fulton","email"=>"a#faucibusorciluctus.edu"),
array("id"=>5,"name"=>"Neville","email"=>"eleifend#consequatlectus.com"),
array("id"=>6,"name"=>"Jasper","email"=>"lectus.justo#miAliquam.com"),
array("id"=>7,"name"=>"Neville","email"=>"Morbi.non.sapien#dapibusquam.org"),
array("id"=>8,"name"=>"Neville","email"=>"condimentum.eget#egestas.edu"),
array("id"=>9,"name"=>"Ronan","email"=>"orci.adipiscing#interdumligulaeu.com"),
array("id"=>10,"name"=>"Raphael","email"=>"nec.tempus#commodohendrerit.co.uk"),
];
function filter($item) {
$mailfilter = Yii::$app->request->getQueryParam('filteremail', '');
if (strlen($mailfilter) > 0) {
if (strpos($item['email'], $mailfilter) != false) {
return true;
} else {
return false;
}
} else {
return true;
}
}
$filteredresultData = array_filter($resultData, 'filter');
$mailfilter = Yii::$app->request->getQueryParam('filteremail', '');
$namefilter = Yii::$app->request->getQueryParam('filtername', '');
$searchModel = ['id' => null, 'name' => $namefilter, 'email' => $mailfilter];
$dataProvider = new \yii\data\ArrayDataProvider([
'key'=>'id',
'allModels' => $filteredresultData,
'sort' => [
'attributes' => ['id', 'name', 'email'],
],
]);
echo GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
[
'attribute' => 'name',
'value' => 'name',
],
[
"attribute" => "email",
'filter' => '<input class="form-control" name="filteremail" value="'. $searchModel['email'] .'" type="text">',
'value' => 'email',
]
]
]);
On the previous soultion. I created a loop to make the filters, columns and searchModel.
$items = [
array("id" => 1, "name" => "Cyrus", "email" => "risus#consequatdolorvitae.org"),
array("id" => 2, "name" => "Justin", "email" => "ac.facilisis.facilisis#at.ca"),
array("id" => 3, "name" => "Mason", "email" => "in.cursus.et#arcuacorci.ca"),
array("id" => 4, "name" => "Fulton", "email" => "a#faucibusorciluctus.edu"),
array("id" => 5, "name" => "Neville", "email" => "eleifend#consequatlectus.com"),
array("id" => 6, "name" => "Jasper", "email" => "lectus.justo#miAliquam.com"),
array("id" => 7, "name" => "Neville", "email" => "Morbi.non.sapien#dapibusquam.org"),
array("id" => 8, "name" => "Neville", "email" => "condimentum.eget#egestas.edu"),
array("id" => 9, "name" => "Ronan", "email" => "orci.adipiscing#interdumligulaeu.com"),
array("id" => 10, "name" => "Raphael", "email" => "nec.tempus#commodohendrerit.co.uk"),
];
$searchAttributes = ['id', 'name', 'email'];
$searchModel = [];
$searchColumns = [];
foreach ($searchAttributes as $searchAttribute) {
$filterName = 'filter' . $searchAttribute;
$filterValue = Yii::$app->request->getQueryParam($filterName, '');
$searchModel[$searchAttribute] = $filterValue;
$searchColumns[] = [
'attribute' => $searchAttribute,
'filter' => '<input class="form-control" name="' . $filterName . '" value="' . $filterValue . '" type="text">',
'value' => $searchAttribute,
];
$items = array_filter($items, function($item) use (&$filterValue, &$searchAttribute) {
return strlen($filterValue) > 0 ? stripos('/^' . strtolower($item[$searchAttribute]) . '/', strtolower($filterValue)) : true;
});
}
echo GridView::widget([
'dataProvider' => new ArrayDataProvider([
'allModels' => $items,
'sort' => [
'attributes' => $searchAttributes,
],
]),
'filterModel' => $searchModel,
'columns' => array_merge(
$searchColumns, [
['class' => 'yii\grid\ActionColumn']
]
)
]);
here are some improvements for the filtering function
function ($item) {
$mailfilter = strtolower(Yii::$app->request->getQueryParam('filteremail', ''));
if (strlen($mailfilter) > 0) {
return strpos(strtolower($item['email']), $mailfilter) !== false;
} else {
return true;
}
}
Use strtolower() in both places($item['email']) & mailfilter) function if you want your filter to be not case sensitive
Check also type for strpos() ("!== false" instead of "!= false") function, otherwise, it will not work while trying to filter for the first characters of the string
A dataprovider :
if ($this->load($params)) {
$name = strtolower(trim($this->name));
$resultData= array_filter($resultData, function ($role) use ($name){
return (empty($name) || strpos((strtolower(is_object($role) ? $role->name : $role['name'])),$name) !== false);
});
}
$dataProvider = new ArrayDataProvider([
'key'=>'id',
'allModels' => $resultData,
'sort' => [
'attributes' => ['id', 'name', 'email'],
],
]);
https://getyii.com/topic/736

Add key and value from other array of hash

I have two array of hashes .Both have similar values in them but i want to create new key in the hash that will have the some values of second array of hash.
First Array:
[
{ area_code => 93, name => 'Afghanistan', code => 'AF', slno => 4554 },
{ area_code => 1684, name => 'American Samoa', code => 'AS', slno => 4557 },
];
Second Array:
[
{ city => "Berat", country => "AS", id => 134368 },
{ city => "Durres", country => "AS", id => 138466 },
{ city => "Kabul", country => "AF", id => 142462 },
];
Now in the first hash i have key code whose value is similar to the second hash key country .So i want to add a new key in the second array of hash which will be country_name.And the country_name value will be the value of first array of hash name.
So how can we do this please help me in this
use strict;
use warnings;
my $a1 = [
{ area_code => 93, code => "AF", name => "Afghanistan", slno => 4554 },
{ area_code => 1684, code => "AS", name => "American Samoa", slno => 4557 },
];
my $a2 = [
{ city => "Berat", country => "AS", id => 134368 },
{ city => "Durres", country => "AS", id => 138466 },
{ city => "Kabul", country => "AF", id => 142462 },
];
my %h = map { $_->{code} => $_ } #$a1;
for my $v (#$a2) {
$v->{country_name} = $h{ $v->{country} }{name};
}
This is a similar idea to #mpapec's, but, I think, a little cleaner.
use strict;
use warnings;
my #array1 = (
{ area_code => 93, name => 'Afghanistan', code => 'AF', slno => 4554 },
{ area_code => 1684, name => 'American Samoa', code => 'AS', slno => 4557 },
);
my #array2 = (
{ country => 'AS', city => 'Berat', id => 134368 },
{ country => 'AS', city => 'Durres', id => 138466 },
{ country => 'AF', city => 'Kabul', id => 142462 },
);
{
my %names = map { $_->{code} => $_->{name} } #array1;
$_->{country_name} = $names{ $_->{country} } for #array2;
}
use Data::Dump;
dd \#array2;
output
[
{
country => 'AS',
city => 'Berat',
id => 134368,
country_name => 'American Samoa',
},
{
country => 'AS',
city => 'Durres',
id => 138466,
country_name => 'American Samoa',
},
{
country => 'AF',
city => 'Kabul',
id => 142462,
country_name => 'Afghanistan',
},
]

creating hash from variables to be used in json encode/decode perl

i'm trying to create a test module to test json encoding. i am having issues creating variables that will output correctly with the json encode/decode. if i use just the $cat_1 in the #cats array, it will work fine. however, using both, it prints out "HASH(..." as you can see below.
use strict;
use JSON;
use Data::Dump qw( dump );
my $cat_1 = {'name' => 'cat1', 'age' => '6', 'weight' => '10 kilos', 'type' => 'siamese'};
my $cat_2 = {'name' => 'cat2', 'age' => '10', 'weight' => '13 kilos', 'type' => 'siamese'};
my #cats;
push(#cats, $cat_1);
push(#cats, $cat_2);
my $dog_1 = {'name' => 'dog1', 'age' => '7', 'weight' => '20 kilos', 'type' => 'siamese'};
my $dog_2 = {'name' => 'dog2', 'age' => '5', 'weight' => '15 kilos', 'type' => 'siamese'};
my #dogs;
push(#dogs, $dog_1);
push(#dogs, $dog_2);
my $pets = {'cats' => #cats, 'dogs' => #dogs};
my $a = { 'id' => '123', 'name' => 'Joe Smith', 'city' => "Chicago", 'pets' => $pets };
my $json = JSON->new->allow_nonref;
my $encoded = $json->encode($a);
my $decoded = $json->decode( $encoded );
print "\ndump cat_1\n";
dump $cat_1;
print "\ndump cats\n";
dump #cats;
print "\n\nOriginal\n";
dump $a;
print "\n\n";
print "Encoded\n";
print $encoded;
print "\n\n";
print "Decoded\n";
dump $decoded;
print "\n\n";
output
dump cat_1
{ age => 10, name => "cat1", type => "siamese", weight => "10 kilos" }
dump cats
(
{ age => 10, name => "cat1", type => "siamese", weight => "10 kilos" },
{ age => 10, name => "cat2", type => "siamese", weight => "3 kilos" },
)
Original
{
city => "Chicago",
id => 123,
name => "Joe Smith",
pets => {
"cats" => { age => 10, name => "cat1", type => "siamese", weight => "10 kilos" },
"HASH(0x176c3170)" => "dogs",
"HASH(0x1785f2d0)" => { age => 10, name => "dog2", type => "siamese", weight => "3 kilos" },
},
}
Encoded
{"city":"Chicago","pets":{"HASH(0x1785f2d0)":{"weight":"3 kilos","name":"dog2","type":"siamese","age":"10"},"cats":{"weight":"10 kilos","name":"cat1","type":"siamese","age":"10"},"HASH(0x176c3170)":"dogs"},"name":"Joe Smith","id":"123"}
Decoded
{
city => "Chicago",
id => 123,
name => "Joe Smith",
pets => {
"cats" => { age => 10, name => "cat1", type => "siamese", weight => "10 kilos" },
"HASH(0x176c3170)" => "dogs",
"HASH(0x1785f2d0)" => { age => 10, name => "dog2", type => "siamese", weight => "3 kilos" },
},
}
This line
my $pets = {'cats' => #cats, 'dogs' => #dogs};
is a red flag. It's valid Perl, but it's not doing what you would expect. Perl will flatten your lists in this construction, so if #cats contains ($cat_1,$cat_2) and #dogs containts ($dog_1,$dog_2), your expression is parsed as
my $pets = { 'cats', $cat_1, $cat_2, 'dogs', $dog_1, $dog_2 };
which is like
my $pets = { 'cats' => $cat_1, $cat_2 => 'dogs', $dog_1 => $dog_2 }
with the hash references $cat_2 and $dog_1 getting stringified before being used as hash keys.
Hash values must be scalar values, not arrays. But array references are OK. Try:
my $pets = {'cats' => \#cats, 'dogs' => \#dogs};
The problem is in the creation of $pets:
my $pets = {'cats' => #cats, 'dogs' => #dogs};
Is roughly equivalent to:
my $pets = {'cats', {name => 'cat1', ...}, {name => 'cat2', ...},
'dogs', {name => 'dog1', ...}, {name => 'dog2, ...} };
Which is the same as:
my $pets = {
'cats' => {name => 'cat1', ...},
{name => 'cat2'}, => 'dogs',
{name => 'dog1', ...}, => {name => 'dog2}
};
You want to use ArrayRefs:
my $pets = {'cats' => \#cats, 'dogs' => \#dogs};
Which is:
my $pets = {
'cats' => [
{name => 'cat1', ...},
{name => 'cat2', ...},
],
'dogs' => [
{name => 'dog1', ...},
{name => 'dog2', ...},
],
};
Which is also how you could declare the whole data structure at once.

Resources