Match Array to a Value within an Array of References - Perl - arrays

I have the following array of references to arrays:
my #holidays = [[2012,'01','02'],[2012,'01','16'],[2012,'02','20'],[2012,'04','16'],[2012,'05','28'],[2012,'07','04'],[2012,'09','03'],[2012,'10','08'],[2012,'11','12'],[2012,'11','22'],[2012,'12','25']];
Which are IRS recognized legal holidays during 2012. I would like to match the array #dueDate to a value in that array and return 1 or true if it is present.
while ($holidays[#dueDate]){
print ("Found Holiday \t join('-',#dueDate)");
#dueDate = Add_Delta_Days(#dueDate, 1);
if ( Day_of_Week(#dueDate) > 5){
#dueDate = Monday_of_Week((Week_Number(#dueDate)+1), $dueDate[0]);
}
}
Is my current attempt at this - the condition of the while statement is never true. I've tried a few different combinations of referencing and dereferencing holidays to no avail.
What would the best way be to manipulate the evaluation within the while statement such that the block executes when #dueDate contains a date within my array above.
Note: #dueDate is a Date::Calc standard array - (Year, Month, Day)

This should put you on the right track. Two problems I see with your code - an array of arrays should have normal parentheses on the outer part, and use the ~~ operator to compare arrays for equality.
my #holidays = ([2012,'01','02'],[2012,'01','16'],[2012,'02','20'],[2012,'04','16'],
[2012,'05','28'],[2012,'07','04'],[2012,'09','03'],[2012,'10','08'],[2012,'11','12'],
[2012,'11','22'],[2012,'12','25']);
my $i;
my #duedate = [2012, '01', '02'];
for ($i = 0; $i < #holidays; $i++)
{
if (#holidays[$i] ~~ #duedate)
{
print "matched!!";
}
}

First,
my #holidays = [[2012,'01','02'],...,[2012,'12','25']];
should be
my #holidays = ([2012,'01','02'],...,[2012,'12','25']);
You're creating an array with a single element.
Probably the best way to achieve what you want is to use a hash.
my %holidays = map { join('-', #$_) => 1 } #holidays;
Then all you need is
while ($holidays{join('-', #dueDate)}) {
my $dow = Day_of_Week(#dueDate);
#dueDate = Add_Delta_Days(#dueDate,
$dow == 5 || $dow == 6 ? 8 - $dow : 1);
}

This is my answer, working on Perl 5.14, also I use smartmatching ~~ operator to compare two arrays.
You assign to array #holidays = [[2012,'01','02'], ]; isn't correct actually you assign anonymous array [ ['2012', '01', '02'], ] to first element of #holidays.
use v5.14;
my #holidays = ( ['2012', '01', '02'], ['2012', '01', '16'] );
my #due_date = ( '2012', '01', '16' );
for my $holiday (#holidays) {
if (#$holiday ~~ #due_date) {
say "holiday match";
}
}

Okay, a few things:
1: Lists are contained in parentheses, and literal array references are written between brackets. So, you should have:
my #holidays = ([2012,'01','02'],[2012,'01','16'],[2012,'02','20'],[2012,'04','16'],[2012,'05','28'],
[2012,'07','04'],[2012,'09','03'],[2012,'10','08'],[2012,'11','12'],[2012,'11','22'],[2012,'12','25']);
2: When you look at $holidays[#dueDate], you're calling everything in scalar context. In particular, since #dueDate has three elements, you're only looking at $holidays[3].
3: Unless you're writing a piece of throwaway code, always use strict; and use warnings;.
So, you want something like this:
use strict;
use warnings;
my #holidays = ([2012,'01','02'],[2012,'01','16'],[2012,'02','20'],[2012,'04','16'],[2012,'05','28'],
[2012,'07','04'],[2012,'09','03'],[2012,'10','08'],[2012,'11','12'],[2012,'11','22'],[2012,'12','25']);
my #dueDates=([2012,'01','01'],[2012,'01','02'],[2012,'01','03']); #Or whatever
my #due_dates_that_are_holidays=();
foreach my $due_date(#dueDates)
{
foreach my $holiday(#holidays)
{
my ($h_y,$h_m,$h_d)=#$holiday; #Capturing year month and day from the array reference
my ($d_y,$d_m,$d_d)=#$due_date; #Ditto for the due date
if($h_y == $d_y and $h_m eq $d_m and $h_d eq $d_d)
{
push #due_dates_that_are_holidays,$due_date;
}
}
}
print join("-",#{$_}) . "\n" foreach(#due_dates_that_are_holidays);
The above code produces the following output:
2012-01-02

Related

how to use array in any() function?

I can run a statement like
select 'a' like any('a',b'), but is it still possible to run this statement if ('a','b') were in an array?
select 'a' like any(array_construct('a','b')) doesn't work.
You can use a JavaScript UDF to approximate this behavior. Rather than trying to get JavaScript to simulate the like syntax, it's probably better to use richer, more expressive Regular Expressions. This UDF will return true if any array member matches that regexp pattern, false if none do, and null if the regex pattern is invalid or it encounters an unexpected error:
create or replace function LIKE_ANY_ARRAY("arr" array, "pattern" string)
returns boolean
language javascript
strict immutable
as
$$
"option strict"
try {
var regex = RegExp(pattern,"g")
for(let i=0; i<arr.length; i++) {
if(regex.test(arr[i])) return true;
}
return false;
} catch {
return null;
}
$$;
select like_any_array(array_construct('a','b'), 'a'); -- True
select like_any_array(array_construct('abcde','b'), '[a-z]{5}'); -- True
select like_any_array(array_construct('abcde','b'), '[a-z]{8}'); -- False, none have enough letters
select like_any_array(array_construct(2,'b'), '[a-z]{8}'); -- Auto-casting
select like_any_array(array_construct('a', 'b'), '['); -- Invalid regex pattern returns NULL
This is returning a Boolean to approximate the behavior of the LIKE ANY function, but could very easily be converted to returning an array of all the matching members or an integer representing the first match, etc.
You could turn you array into a string that resembles a regex and match against that
where 'a' rlike array_to_string( ['a','b'],'|')

Save check constraint values to variables

I get a table check constraint definition this way:
select a.CHECK_CLAUSE
from INFORMATION_SCHEMA.CHECK_CONSTRAINTS a,INFORMATION_SCHEMA.TABLE_CONSTRAINTS b
where b.TABLE_NAME = 'table name'
For my example, suppose running this query returns this:
[([depname]='mathematics' OR [depname]='electronics' OR [depname]='computer science')]
How do I assign the values ​​specified in the check constraint into variables? i.e. computer science, mathematics and electronics?
It looks like you're getting a string returned. What you can do is split the string on instances of OR and store that in an array, and then run through the array and split each element on = to isolate the values. So, if you were to do this in PHP, the code might look something like this:
// For reasons of simplicity we will assume the result is stored in $result,
// and the leading [( and trailing )] have already been removed
$values = array();
$resultsplit = explode(' OR ', $result);
/* $resultsplit is now an array:
* $resultsplit[0] = "[depname]='mathematics'"
* $resultsplit[1] = "[depname]='electronics'"
* $resultsplit[2] = "[depname]='computer science'"
*/
if ($result != '') {
foreach ($resultsplit as $rs) {
$rsparts = explode('=', $rs);
/* $rsparts is now an array. On the first element:
* $rsparts[0] = "[depname]"
* $rsparts[1] = "'mathematics'"
* So all we need to do is stick $rsparts[1] into $values
*/
$values[] = $rsparts[1];
}
}
This will put all of the values into the array $values (including the single-quotes at the beginning and end) for you to do with as you please, regardless of how many there are. If PHP is not the language you have available to you, the same method should still work in your language of choice.

add key=>value pair to associative array in php While loop

I create a simple associative array in a WHILE loop. The key is the field name and the value is a Unix timestamp. I would like to add to this array a new key=>value pair 'Date"=>format the Unix timestamp, json_encode the array and return it to a JQ script in an Ajax call. The array looks like this:
Array
( [0] => Array
( [Post_timestamp] => 1370876787 ) [Date] => 2013 06 10 )
However, shouldn't it look like this:
Array
( [0] => Array ( [Post_timestamp] => 1370876787 [Date] => 2013 06 10))
I guess my question is "how do I create the array so that the formatted timestamp and the raw timestamp are a single record"? Right now, it appears as if they are two records.
PHP
$query = "SELECT Post_timestamp FROM Comments LIMIT 1";
$result = mysqli_query($dbc, $query);
while ($rows = mysqli_fetch_assoc($result)) {
$array[] = $rows;
$array['Date'] = date("Y m d", $rows['Post_timestamp']);
}
The problem is you have two different values into the array, what you need to do is push an array that contains both values. This should get you what you want.
$query = "SELECT Post_timestamp FROM Comments LIMIT 1";
$result=mysqli_query($dbc,$query);
while ($rows = mysqli_fetch_assoc($result)) {
$rows["Date"] = date("Y m d",$rows['Post_timestamp']);
$array[] = $rows;
}

Querying multiple times in Oracle using perl returns only the first query

Note: I have corrected the variable differences and it does print the query from the first set but it returns nothing from the second set. If I use the second set only it works.
In the code below, I have some_array which is array of array the array contains text like name. So
#some_array= ([sam, jon, july],[Mike, Han,Tommy],[angie, sita, lanny]);
Now when I querying the list like 'sam jon july' first and 'mike han tommy' . Only the execute return the result from the first list others is undef. I don't know why any help will be appreciated.
my $pointer;
my $db = $db->prepare_cached("
begin
:pointer := myFun(:A1);
end;
") or die "Couldn't prepare stat: " . $db->errstr;
$db->bind_param_inout(":pointer",\$pointer,0,{ ora_type => ORA_RSET });
for (my $i=0; $i < #some_array ; $i++) {
my #firstarray = #{$some_array[$i]};
my $sql = lc(join(" ", #firstarray));
print "<pre>$sql</pre>\n";
$db->bind_param(":A1",$sql);
$db->execute();
print "<pre>".Dumper($db->execute())."</pre>\n";
}
Just like everyone told you on the last question you asked, initialize your array with parentheses, not nested brackets.
#some_array= ([sam, jon, july],[Mike, Han,Tommy],[angie, sita, lanny])
not
#some_array= [[sam, jon, july],[Mike, Han,Tommy],[angie, sita, lanny]]
You would also benefit tremendously from including
use strict;
use warnings;
at the top of all of your programs. That would catch the strange way you are trying to initialize #some_array, and it would catch your inconsistent usage of #sql and #query. update and $sdh and $db and $dbh.

Perl - Hash of Arrays across Module

I am a bit new to Perl and I need some help regarding moving my Hash of Arrays across Modules.
Currently I have a db module that stores an array like so:
sub getSourceCriteria {
my($self) = shift();
my($sourceId) = shift();
chomp $sourceId;
my(%criteria) =();
$logger->debug("Getting records for Source ID: " . $sourceId);
$dbh=DBI->connect('dbi:ODBC:StkSkrnDB', 'RTETET', 'XXuser01',{ RaiseError => 1, AutoCommit => 0 }) || \
$logger->err_die("Database connection not made: $DBI::errstr\n");
my($sth) = "select a.criteria_id, a.criteria_type, a.criteria_props,a.generalcriteria_id,b.field_id ";
$sth = $sth . "from t_criteria a, t_sourceMapping b where a.generalcriteria_id = (select generalcriteria_id from t_sourcecriteria where source_id =?) ";
$sth = $sth . "and a.criteria_id=b.criteria_id";
my($qry) = $dbh->prepare($sth);
$qry->execute($sourceId) || $logger->error("Could not query for Source Criteria: $DBI::errstr\n");
my(#row)=();
my($tempCount) = 0;
while ( #row = $qry->fetchrow_array ) {
$tempCount = scalar #row;
$logger->debug("Size of retrieved SQL Array : $tempCount");
$criteria{$row[0]} = \#row;
###{$criteria{$row[0]} } = \#row;
}
return %criteria;
}
And I have a seperate perl script that reads the SQL output from the code above:
foreach my $criteria (keys %criterias) {
#temp = exists( $criterias{$criteria} ) ? #{ $criterias{$criteria} } : ();
##my $tempStr = exists( $criterias{$criteria} ) ? "Yes" : "No";
$arraySize = scalar #temp;
$logger->debug("GENERALCRITERIA_ID is $GENERALCRITERIA_ID and size of array is $arraySize and $temp[0]");
$genCrit_ID = $temp[$GENERALCRITERIA_ID];
$logger->debug("Criteria ID $criteria has Gen Criteria ID $genCrit_ID");
if (0!=$generalCriteria_ID || $generalCriteria_ID != $genCrit_ID ) { ## test for uniqueness
$generalCriteria_ID = -1;
}
else {
$generalCriteria_ID = $genCrit_ID;
}
}# do something with $key and $value
$generalCriteria = $generalCriteria_ID;
}
The problem is I keep getting 0 as the retrieved array size( 2nd snippet) even though when I store the array ( in the 1st snippet ) I check and get the actual array size.
Please any help/clarification would be greatly appreciated.
EDIT
Added more code in the DB interface code.
In your while loop, you are assigning to #row and then storing a reference to that array. However, each time the loop iterates, you are replacing the contents of #row without declaring a new array. So at the end, each of your references point towards the same thing.
In your code here:
my(#row)=();
my($tempCount) = 0;
while ( #row = $qry->fetchrow_array ) {
$tempCount = scalar #row;
$logger->debug("Size of retrieved SQL Array : $tempCount");
$criteria{$row[0]} = \#row;
###{$criteria{$row[0]} } = \#row;
}
Each time the while loop iterates, you assign new values to the #row array. But since the my(#row)=(); line occurs outside of the loop, the #row array is always the same. So each time you assign to the array, you are changing what is stored in all of the references you have already taken.
To fix the problem, you need to declare a new array for each iteration. The simplest way to do this is to move the declaration into the while condition:
my($tempCount) = 0;
while ( my #row = $qry->fetchrow_array ) {
$tempCount = scalar #row;
$logger->debug("Size of retrieved SQL Array : $tempCount");
$criteria{$row[0]} = \#row;
###{$criteria{$row[0]} } = \#row;
}
Now each time you take the reference \#row you will be getting a reference to a new array.
If your $qry->fetchrow_array method returned an array reference, you would not have had the issue:
my $row;
while ($row = $qry->fetchrow_array) {
$logger->debug("Size of retrieved SQL Array : ".#$row);
$criteria{$$row[0]} = $row; # already a reference
}
But I would still write that as while (my $row = ... in my own code, since keeping scopes small is a good thing.

Resources