Ruby Search Array of Hashes and Arrays - arrays

I have an array of hashes which also include an array:
machines = [{ 'name' => 'ldapserver1', 'ip' => '10.199.0.10',
'role' => ['server', 'initial'] },
{ 'name' => 'ldapserver2', 'ip' => '10.199.0.11',
'role' => ['server', 'secondary'] },
{ 'name' => 'ldapclient1', 'ip' => '10.199.0.12',
'role' => 'client' },
{ 'name' => 'ldapclient2', 'ip' => '10.199.0.13',
'role' => 'client' }]
I want to search thru it to get the machine with a matching role.
I can use this to get machines with the client role:
results = #machines.select { |machine| machine['role'] == 'client' }
[{"name"=>"ldapclient1", "ip"=>"10.199.0.12", "role"=>"client"}, {"name"=>"ldapclient2", "ip"=>"10.199.0.13", "role"=>"client"}]
But when I try to search the array of roles this breaks:
results = machines.select { |machine| machine['role'] == 'server' }
[]
How can I search through the role arrays to find matches for my machines?

This is a perfect use-case for Enumerable#grep:
machines.reject { |m| [*m['role']].grep('server').empty? }
Here a splat is used to produce an array from both Array instance and the String instance.

As per your code the roles can be string or array so safe to check using following
results = machines.select { |machine| Array(machine['role']).include?('server') }
Update: using Array, this method tries to create array by calling to_ary, then to_a on its argument.

That is because 'role' can be a string or an array.
Using #include? will match part of a string if it's a string. Or fully match a string inside an array.
Try:
results = machines.select { |machine| machine['role'].include?('server') }
Or more robust
results = machines.select do |machine|
r = machine['role']
if r.is_a? String
r == 'server'
else
r.include?('server')
end
end

Related

Store multidimension array in userdata session codeigniter

I want to store multi dimension array in codeigniter userdata session.
when i store a simple array it works fine. but in multi dimension it store nothing. Is there a way to store multi dimension array in session.
My code is:
foreach ($unique_data as $unique_type) {
$indexes = index_unique_values($product_all_data, 'type', $unique_type['type']);
foreach ($indexes as $key) {
$product_name = $product_all_data[$key]['name'];
$product_type = $product_all_data[$key]['type'];
$product_status = $product_all_data[$key]['status'];
$cost = $product_all_data[$key]['cost'];
$price = $product_all_data[$key]['price'];
$barcode = $product_all_data[$key]['barcode'];
$product_type_all_prod[] = array('name' => $product_name, 'type' => $product_type, 'status' => $product_status, 'cost' => $cost, 'price' => $price, 'barcode' => $barcode, 'cat_name' => '');
}
}
$product_bytype_array = array("product_by_type" => $product_type_all_prod);
$this->session->set_userdata($product_bytype_array);
Thank you.
What if you try something like...
$this->session->set_userdata(['product_data' =>$product_bytype_array]);
You can check that you are actually generating an array in the format you are expecting.
Then check that the Stored result is in the format you are expecting.
// What's in the resulting array that we want to store in the session?
var_dump($product_type_all_prod);
$product_bytype_array = array("product_by_type" => $product_type_all_prod);
$this->session->set_userdata($product_bytype_array);
//What's in the array in the session
var_dump($this->session->userdata('product_by_type'));
That should help.
NOTE: I've tested this using CI 3.1.0 with sessions configured as the types File and then as Database.

Perl: Filter AoH output

I'm trying to sort my AoH which looks like this:
$VAR1 = [
{
'Name' => 'John',
'Lastname' => 'Derp',
'Organization' => 'Finance',
'OfficeNR' => '23',
'ID' => '145'
},
{
'Name' => 'Kate',
'Lastname' => 'Herp',
'Organization' => 'HR',
'OfficeNR' => '78',
'ID' => '35'
},
{
'Name' => 'Jack',
'Lastname' => 'Serp',
'Organization' => 'Finance',
'OfficeNR' => '23',
'ID' => '98'
}
];
What I'm trying to do is to filter my output using keys from AoH, for example print out only those who have 'Organization' => 'Finance'.
I've tried to solve it using new array:
my #SortedAoH = sort { {Organization=>{'Finance'}} } #AoH;
But it doesn't work.
What you want is grep, not sort. You are getting the basic syntax of equivalence checking wrong as well.
Anyway, the filter is:
my #finance_orgs = grep { $_->{'Organization'} eq 'Finance' } #AoH;
The #finance_orgs variable will now only include the ones with Organization set to Finance.
Just an explanation of the pieces:
The $_ variable is the variable that gets assigned whenever the value is implied in a block, such as in grep or map or in a for loop without an explicitly named variable.
$_->{'Organization'} performs a hash lookup on the hash as it iterates through each entry in your array.
eq is the operator used to test for string equivalence (as opposed to == which tests for numeric equivalence).

searching a perl hash for a value

I'm reading in an xml file using XMLin and it gives me this...
'Date' => '01Jan2013',
'Total' => 3,
'Details' => {
'Detail' => [
{
'Name' => 'Bill',
'ID' => '123',
'IP' => '255.255.255.1'
},
{
'Name' => 'Ted',
'ID' => '456',
'IP' => '255.255.255.2'
},
{
'Name' => 'Fred',
'ID' => '789',
'IP' => '255.255.255.3'
},
]
}
I'm trying to search the {Detail}[Name] values for a particular name. So I want to search for Fred to get his name and IP address.
foreach my $ruleline ($pricesettings->{Details}{Detail}['Name']){
if ($pricesettings->{Details}{Detail}["Name"] eq "Fred") {
print "Found you\n";
}
else {
print "Not found\n";
}
}
But even if I print Dumper($pricesettings->{Details}{Detail}['Name']) within the for loop it only prints the first record entries for Bill.
Ideally I want to see output like
Name => 'Bill'<br>
Name => 'Ted'<br>
Name => 'Fred'<br>
Then if Fred is found I want to get Fred's IP address or ID. I have no problem finding or comparing the value 'Date' or 'Total' for example, but each grouping under 'Detail' is causing me a problem.
your code snippet is slightly off. instead, try
foreach my $ruleline (#{$pricesettings->{Details}{Detail}}){
if ( $ruleline->{"Name"} eq "Fred") {
print "Found you\n";
}
else {
print "Not found\n";
}
}
In order to arrive at the output you actually aim at, try the following:
foreach my $ruleline (#{$pricesettings->{Details}{Detail}}){
print "Name -> '$$ruleline{Name}'" ;
if ( $$ruleline{Name} eq "Fred") {
print "; ID -> '$$ruleline{ID}', IP -> '$$ruleline{IP}';" ;
}
print "\n";
}
technical explanation:
in your original code you've mixed up arrays and hashes. for complex data structures of the kind you employ consider switching to an oo programming style, maybe using Moose (though that might be overkill).

Directly access value based on another value in anonymous array of hashes

Given the following anonymous array of hashes:
$AoH = [
{
'FORM_FIELD_ID' => '10353',
'VISIBLE_BY' => '10354',
'FIELD_LABEL' => 'ISINCIDENT',
'VALUE' => '',
'DEFAULT_FIELD_LABEL' => 'Yes No',
'FORM_ID' => '2113',
},
{
'FORM_FIELD_ID' => '10354',
'VISIBLE_BY' => '0',
'FIELD_LABEL' => 'CATEGORY',
'VALUE' => 'zOS Logical Security (RACF)',
'DEFAULT_FIELD_LABEL' => 'CATEGORY',
'FORM_ID' => '2113',
},
{
'FORM_FIELD_ID' => '10368',
'VISIBLE_BY' => '10354',
'FIELD_LABEL' => 'STARTDATE',
'VALUE' => '',
'DEFAULT_FIELD_LABEL' => 'REQTYPE',
'FORM_ID' => '2113',
}
];
How would I directly access the FIELD_LABEL value given that I knew the FORM_FIELD_ID is 10353?
I know I can loop through #$AoH and conditionally find $_->{FIELD_LABEL} based on $_->{FORM_FIELD_ID} == 10353, but is there anyway to directly access the wanted value if one of the other values in the same hash is known?
No, not unless you change your data structure. You could e.g. index the records by their form field id:
my %by_form_field_id = map { $_->{FORM_FIELD_ID} => $_ } #$AoH;
Then:
my $field_label = $by_form_field_id{10353}{FIELD_LABEL};
Without changing the data structure, you really have to grep:
my $field_label = (grep { $_->{FORM_FIELD_ID} == 10353 } #$AoH)[0]->{FIELD_LABEL};
You'd have to write a function loop through #array and examine the %hash or maybe use the builtin grep method:
say $_->{FIELD_LABEL} for (grep { $_->{FORM_FIELD_ID} == 10353 } #$AoH )
works. And so does this:
say %$_->{FIELD_LABEL} for (grep { $_->{FORM_FIELD_ID} == 10353 } #$AoH )
but it gives a Using a hash as a reference is deprecated warning (with pumpkin perl-5.16.3).

Kohana Database instances containts wrong data

I have a problem with Kohana database.
Sometimes I have error
ErrorException [ Recoverable Error ]
Argument 1 passed to Kohana_Database_Query_Builder_Select::compile() must be an instance of Database, string given, called in /srv/sites/mysite/www/modules/database/classes/kohana/database/query.php on line 230 and defined
It's happens because in Database:$instances containts string "dances", but should contain array database configurations.
This my config:
<?php defined('SYSPATH') OR die('No direct access allowed.');
return array
(
'default' => array
(
'type' => 'MySQL',
'connection' => array(
'hostname' => 'localhost',
'database' => 'chat',
'username' => 'root',
'password' => 'root',
'persistent' => FALSE,
),
'table_prefix' => '',
'charset' => 'utf8',
'caching' => FALSE,
'profiling' => TRUE
)
);
Maybe somebody had problem like this or could help me?
Any query to DB causes error.
Like this:
Jelly::factory('user', $user->id())
or this:
DB::select('value')->from('storage')->where('name', '=', 'salt')->limit(1)->execute();
or this:
ORM::factory('node')->where('type', '=', 'page-homepage')->find();
I don't know why this error happen. I checked all methods are called and I have not found any mistakes.
I solved this problem by write method instance in class Database
public static function instance($name = NULL, array $config = NULL)
{
if ($name === NULL)
{
// Use the default instance name
$name = Database::$default;
}
if ( ! is_array(Database::$instances))
{
Database::$instances = array();
}
if ( ! isset(Database::$instances[$name]))
{
if ($config === NULL)
{
// Load the configuration for this database
$config = Kohana::$config->load('database')->get($name);
}
if ( ! isset($config['type']))
{
throw new Kohana_Exception('Database type not defined in :name configuration',
array(':name' => $name));
}
// Set the driver class name
$driver = 'Database_'.ucfirst($config['type']);
// Create the database connection instance
new $driver($name, $config);
}
return Database::$instances[$name];
}
I add condition As you can see
if ( ! is_array(Database::$instances))
{
Database::$instances = array();
}
I don't like this, but I have no choise.
My wild guess would be that you seem to be overwriting the compile, quote, quote_column, quote_identifier, quote_table or execute method from Kohana_Database in your code or simply calling ->execute('dances') should trigger this error.
the compile method shouldn't be called directly, it's an internal function that is called from execute()
Any of these functions take $db as the first parameter. Don't pass anything, since you want to use the database set in your config file, without trying to set it manually in your query builder.

Resources