I am trying to return today's birthdays. This is what I have right now, which works, but I need to grab the month and day to input into the statement. I thought maybe I could grab them from localtime, but that didn't work out. Any suggestions would be appreciated.
sub author_birth {
my ($self) = #_;
my ($day,$month) = (localtime())[3..4];
my $author_result = $self->search_like(
{
birth => '%03-20'
},
{
select => [
'id',
'complete_name',
],
#result_class => 'DBIx::Class::ResultClass::HashRefInflator'
}
);
my #author_ids = ();
while (my $row = $author_result->next) {
push #author_ids, $row->id;
}
return $self->get_author_info_by_id(\#author_ids);
}
I ended up doing something like this.
my ($self) = #_;
my $conc = '%';
my $datetime = Time::Piece->new->strftime('%m-%d');
my $date = $conc . $datetime;
my $author_result = $self->search_like(
{
birth => $date,
},
{
select => [
'id',
'complete_name',
],
#result_class => 'DBIx::Class::ResultClass::HashRefInflator'
}
);
Related
I have a hash variable as a tree:
\%data = {
'node' => {
'RN:4' => {
'next' => {
'1' => {
'RN:23' => {
'next' => {
'1' => {
'RN:29' => {
'end' => 1
}
},
'2' => {
'RN:32' => {
'next' => {
'1' => {
'RN:30' => {
'end' = 1
}
}
}
}
}
}
I want to convert this tree to correct paths like this:
1, RN:4 >> RN:23 >> RN:29
2, RN:4 >> RN:23 >> RN:32 >> RN:30
I have tried some recursive code but alway get wrong path.
Help me please !
The data structure is wholly too complicated. Hashes are being used as arrays, and it would be easier if the id wasn't used as the key. It would be better if a node looked like this:
{
id => ...,
children => [ ... ]
}
The structure would become
[
{
id => 'RN:4',
children => [
{
id => 'RN:23',
children => [
{
id => 'RN:29',
children => []
},
{
id => 'RN:32',
children => [
{
id => 'RN:30',
children => []
}
]
}
]
}
]
}
]
You need the id of all ancestors so we pass a long a list of the ancestors as the parameters.
use 5.016;
sub print_paths {
my $i = 0;
my $helper = sub {
my $node = $_[-1];
my $children = $node->{children};
if (#$children) {
__SUB__->(#_, $_) for #$children;
} else {
say $i, ", ", join(" >> ", map { $_->{id} } #_);
}
};
$helper->(#_);
}
print_paths($_) for #$roots;
The above assumes the ends are the nodes with no children. If your ends can have children, you have a trie. Simply add end => 1 to the end nodes and use the following as the core of the visitor:
if (#$children) {
__SUB__->(#_, $_) for #$children;
}
if ($node->{end}) {
say $i, ", ", join(" >> ", map { $_->{id} } #_);
}
With your format, it's trickier (and more expensive).
$node->{id} is replaced with (keys(%$node))[0].
$node->{children} is replaced with $node->{$id}{next}.
$node->{end} is replaced with $node->{$id}{end}.
for my $child (#$children) is replaced with for (my $j=1; my $child = $children->{$j}; ++$j).
use 5.016;
sub print_paths {
my $i = 0;
my $helper = sub {
my $node = $_[-1];
my $id = (keys(%$node))[0];
my $children = $node->{$id}{next};
if ($children) {
for (my $j=1; my $child = $children->{$j}; ++$j) {
__SUB__->(#_, $child) for #$children;
}
}
if ($node->{$id}{end}) {
say $i, ", ", join(" >> ", map { (keys(%$node))[0] } #_);
}
};
$helper->(#_);
}
print_paths($data->{node});
I am having dictionary like this.
print Dumper($emp)
$VAR1 = {
'mike' => {
'country' => {
'US' => {
'pop' => 100
}
}
}
}
I want to append a new entry inside 'country' like this.
$VAR1 = {
'mike' => {
'country' => {
'US' => {
'pop' => 100
},
'Canada' => {
'pop' => 101
}
}
}
}
Right now I am building it like this
$emp -> {$name}{country} = getCountry();
sub getCountry{
....
return country;
}
It's not clear what getCountry returns. Seeing as it's a single scalar, I'm going to assume it's a hash of countries keyed by name despite the name.
{ Canada => { pop => 101 } }
A simple way to merge two hashes is
%h = ( %h, %new );
so
%{ $emp->{$name}{country} } = (
%{ $emp->{$name}{country} },
%{ getCountry() },
);
If getCountry were to return the country's name and the country, you'd could use the following:
my ($country_name, $country) = getCountry();
$emp->{$name}{country}{$country_name} = $country;
So, if the hash returned by getCountry returns just a single country, you could also do the following without changing getCountry:
my ($country_name, $country) = %{ getCountry() };
$emp->{$name}{country}{$country_name} = $country;
I have to write to check array ref for more than 3 params. If the value is coming from an array then I have written a foreach loop for that, then chop that and assign to a new variable after concatenating pipe.
Code
if ( defined $args->{hotel} ) {
if ( ref( $args->{hotel} ) eq "ARRAY" ) {
foreach my $hotel ( #{ $args->{hotel} } ) {
$hotel .= $hotel . "|";
}
chop($hotel);
$args->{hotel_name} = $hotel;
} else {
$args->{hotel_name} = $args->{hotel};
}
} else {
$args->{hotel_name} = $hotel;
}
if ( defined $args->{country} ) {
if ( ref( $args->{country} ) eq "ARRAY" ) {
foreach my $country_name ( #{ $args->{country} } ) {
$country_name .= $country_name . "|";
}
chop($country_name);
$args->{country_name} = $country_name;
} else {
$args->{country_name} = $args->{country};
}
} else {
$args->{country_name} = $country_name;
}
if ( defined $args->{city} ) {
if ( ref( $args->{city} ) eq "ARRAY" ) {
foreach my $city ( #{ $args->{city} } ) {
$city .= $city . "|";
}
chop($city);
$args->{city_name} = $city;
} else {
$args->{city_name} = $args->{city};
}
} else {
$args->{city_name} = $city;
}
I want to write a function for this kind of work so that there will be no repetition of same code. Please help me; how can we do this in Perl?
You can write:
sub convert_to_name ($$) { # ($value, $fallback_name)
my ($value, $fallback_name) = #_;
if (defined $value) {
if (ref($value) eq 'ARRAY') {
return join '|', #$value;
} else {
return "$value";
}
} else {
return $fallback_name;
}
}
$args->{'hotel_name'} = convert_to_name $args->{'hotel'}, $hotel;
$args->{'country_name'} = convert_to_name $args->{'country'}, $country;
$args->{'city_name'} = convert_to_name $args->{'city'}, $city;
There appear to be some potential bugs in your code, the biggest centering around reusing variable names at lower scopes.
However, of course you can add an iteration loop to your code that would remove the need for 3 nearly identical sections. The following does that by creating a intermediate hash data structure to relate field names to values.
Note: I also simplified the code by inverting the logic if your first if statement so that all ifs could be at the same level. Additionally, it makes sense to use a join instead of rolling your own such functionality.
my %hash = (
hotel => $hotel,
country => $country_name,
city => $city,
);
while ( my ( $field, $value ) = each %hash ) {
if ( !defined $args->{$field} ) {
$args->{"${field}_name"} = $value;
} elsif ( ref( $args->{$field} ) eq "ARRAY" ) {
$args->{"${field}_name"} = join '|', #{ $args->{$field} };
} else {
$args->{"${field}_name"} = $args->{$field};
}
}
Also, if you're comfortable with the Conditional operator, this can be reduced further. However, some would consider this too cluttered:
while ( my ( $field, $value ) = each %hash ) {
$args->{"${field}_name"} = !defined $args->{$field}
? $value
: ref( $args->{$field} ) eq "ARRAY"
? join( '|', #{ $args->{$field} } )
: $args->{$field};
}
Im trying to make a hashes of hashes to uniquely identify the number that only comes under one set of levels. the hash structure looks something like this :
my %gh = {
'Test1' => {
'level1a' => {
'level2b' => {
'level3a' => {
'level4a' => {
'level5' => '63'
}
}
}
}
}
};
Can some please tell me what is the simplest way to traverse the hash so i can get the value 63.
I have been using
my $x = '';
foreach my $l0 (%gh){
foreach my $l1 (%{$l0}){
foreach my $l2 (%$l1){
foreach my $l3 (%{$l2}){
foreach my $l4 (%$l3){
foreach my $l5 (%{$l4}){
$x = $l5;
}
}
}
}
}
}
This process seems to be working fine . But i was just looking for something simpler and shorter;
Thanks in advance
This will work in your case (only hashes, and plain scalar value at the end)
sub hval {
my ($h) = #_;
return map { ref() ? hval($_) : $_ } values %$h;
}
my $gh = {
'Test1' => {
'level1a' => {
'level2b' => {
'level3a' => {
'level4a' => {
'level5' => '63'
}
}
}
}
}
};
my ($x) = hval($gh);
If you use a reference to a hash instead, here is one way:
use warnings;
use strict;
my $gh = {
'Test1' => {
'level1a' => {
'level2b' => {
'level3a' => {
'level4a' => {
'level5' => '63'
}
}
}
}
}
};
print $gh->{Test1}{level1a}{level2b}{level3a}{level4a}{level5}, "\n";
See also: perldoc perldsc and Data::Diver
I have here many-to-many table, i need to get just inserted id - BlogId. lastInsertId() is NULL result. Any ideas?
$table = new Blog_Model_Blog_Table();
$relTable = new Blog_Model_Relation_Table();
$Object = $table->createRow();
$form = new Blog_Form_Blog_Add($Object);
if ($this->getRequest()->isPost() and $form->isValid($_POST)) {
Blog_Model_Blog_Manager::add($Object);
$blogId = $table->getAdapter()->lastInsertId();
foreach ($_POST['category_id'] as $value) {
$relTable->insert(array('id' => $blogId, 'category_id' => $value));
}
Blog_Model_Blog_Manager:
class Blog_Model_Blog_Manager
{
static function add(Blog_Model_Blog_Item &$Object)
{
$data = array(
'time_add' => time(),
'time_edit' => time(),
'url_keyword' => Ap_Filter_Translit::asURLSegment($Object->name)
);
$Object->setFromArray($data)
->save();
}
I make it with mySql function LAST_INSERT_ID():
$blogId = $table->fetchRow($table->select()->from($table)->columns('LAST_INSERT_ID() as idi'));