Re: Array of variables
by choroba (Cardinal) on Apr 27, 2017 at 16:01 UTC
|
@Variable and @Variables are two different... well... variables.
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
my $Map_Request_Date = 'Jan 1 2017 12:00';
my $Map_Due_Date = 'Jan 31 2017 12:00';
my $Map_Cutover_Date = 'Feb 28 2017 23:59';
my $Map_Complete_Date = 'Mar 1 2017 12:01';
my $Map_Approved_Date = 'Dec 31 1999 0:01';
my @Variables = ($Map_Request_Date, $Map_Due_Date, $Map_Cutover_Date,
$Map_Complete_Date, $Map_Approved_Date);
my $X = 0;
for my $Date_Ref (@Variables) {
say $Date_Ref;
$Date_Ref =~ s/ +/ /; #When day is a single digit it creates two w
+hite spaces
my ($Month, $Day, $Year, $Time) = split / /, $Date_Ref, 4;
my %Months = ( Jan => '01', Feb => '02', Mar => '03', Apr => '04
+',
May => '05', Jun => '06', Jul => '07', Aug => '08
+',
Sep => '09', Oct => '10', Nov => '11', Dec => '12
+' );
$Day = "0$Day" if 1 == length $Day;
$Variables[$X++] = "$Year-$Months{$Month}-$Day";
}
say for @Variables;
for (same as foreach ) aliases the values it iterates over, so you don't need the array at all:
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
my $Map_Request_Date = 'Jan 1 2017 12:00';
my $Map_Due_Date = 'Jan 31 2017 12:00';
my $Map_Cutover_Date = 'Feb 28 2017 23:59';
my $Map_Complete_Date = 'Mar 1 2017 12:01';
my $Map_Approved_Date = 'Dec 31 1999 0:01';
for my $Date_Ref ($Map_Request_Date, $Map_Due_Date, $Map_Cutover_Date,
$Map_Complete_Date, $Map_Approved_Date
) {
say $Date_Ref;
$Date_Ref =~ s/ +/ /;
my ($Month, $Day, $Year, $Time) = split / /, $Date_Ref, 4;
my %Months = ( Jan => '01', Feb => '02', Mar => '03', Apr => '04
+',
May => '05', Jun => '06', Jul => '07', Aug => '08
+',
Sep => '09', Oct => '10', Nov => '11', Dec => '12
+' );
$Day = sprintf '%02d', $Day;
$Date_Ref = "$Year-$Months{$Month}-$Day";
}
say for $Map_Request_Date, $Map_Due_Date, $Map_Cutover_Date,
$Map_Complete_Date, $Map_Approved_Date;
Note the usage of sprintf to format the day.
But it's even easier when you use Time::Piece :
#!/usr/bin/perl
use warnings;
use strict;
use feature qw{ say };
use Time::Piece;
my $Map_Request_Date = 'Jan 1 2017 12:00';
my $Map_Due_Date = 'Jan 31 2017 12:00';
my $Map_Cutover_Date = 'Feb 28 2017 23:59';
my $Map_Complete_Date = 'Mar 1 2017 12:01';
my $Map_Approved_Date = 'Dec 31 1999 0:01';
for my $Date_Ref ($Map_Request_Date, $Map_Due_Date, $Map_Cutover_Date,
$Map_Complete_Date, $Map_Approved_Date
) {
say $Date_Ref;
my $tp = 'Time::Piece'->strptime($Date_Ref, '%b %d %Y %H:%M');
$Date_Ref = $tp->ymd;
}
say for $Map_Request_Date, $Map_Due_Date, $Map_Cutover_Date,
$Map_Complete_Date, $Map_Approved_Date;
($q=q:Sq=~/;[c](.)(.)/;chr(-||-|5+lengthSq)`"S|oS2"`map{chr |+ord
}map{substrSq`S_+|`|}3E|-|`7**2-3:)=~y+S|`+$1,++print+eval$q,q,a,
| [reply] [d/l] [select] |
|
|
You did not address this clap trap of non-design:
my $Map_Request_Date = 'Jan 1 2017 12:00';
my $Map_Due_Date = 'Jan 31 2017 12:00';
my $Map_Cutover_Date = 'Feb 28 2017 23:59';
my $Map_Complete_Date = 'Mar 1 2017 12:01';
my $Map_Approved_Date = 'Dec 31 1999 0:01';
for my $Date_Ref ($Map_Request_Date, $Map_Due_Date, $Map_Cutover_Date,
$Map_Complete_Date, $Map_Approved_Date
) {
And we still do not understand what the OP means by "issue do not know how to address an array of variable to place the data back into the array variable ..." | [reply] [d/l] |
|
|
| [reply] |
Re: Array of variables
by stevieb (Canon) on Apr 27, 2017 at 15:48 UTC
|
Always, at the top of your Perl code:
use warnings;
use strict;
Now:
@Variable[$X]=$Year."-".$Months{$Month} ."-" . $Day ;
You have not declared the @Variable array. You have @Variables. Also, when assigning to an array *element*, use scalar context:
$Variables[$X] = ...;
| [reply] [d/l] [select] |
Re: Array of variables
by haukex (Archbishop) on Apr 27, 2017 at 16:08 UTC
|
From the documentation of Foreach Loops: "... the foreach loop index variable is an implicit alias for each item in the list that you're looping over." Meaning you can simply assign back to the $Date_Ref variable in order to assign to the element in the array. You can even modify the original variables by writing for my $Date_Ref ($Map_Request_Date, ...) { ... (Update: It seems choroba has made the same point while I was typing.)
In the following, I've taken the liberty of writing the code the way I might have (see also Use strict and warnings), although I prefer using modules like DateTime (plus DateTime::Format::Strptime) for all my date/time handling needs, even if it seems like overkill sometimes. (Update: Note that I kept your technique of adding a leading zero to $Day instead of switching to sprintf because I wanted to demonstrate using if as a statement modifier, but if I were writing this from scratch I'd have used sprintf instead.)
use warnings;
use strict;
use Data::Dumper;
my %Months = ( 'Jan' => '01', 'Feb' => '02', 'Mar' => '03', 'Apr' =>
+ '04',
'May' => '05', 'Jun' => '06', 'Jul' => '07', 'Aug' => '08',
'Sep' => '09', 'Oct' => '10', 'Nov' => '11', 'Dec' => '12' );
my ($Date1,$Date2) = ('Jul 3 2016 10:45 UTC','Aug 12 2017 11:56 EST')
+;
my @Variables = ($Date1,$Date2);
for my $Date_Ref (@Variables) {
my ($Month,$Day,$Year,$Time) = split ' ', $Date_Ref, 4;
$Day = "0$Day" if length($Day) == 1;
$Date_Ref = $Year."-".$Months{$Month}."-".$Day;
}
print Dumper \@Variables;
__END__
$VAR1 = [
'2016-07-03',
'2017-08-12'
];
Note: split ' ', ..., as opposed to split / /, ... has a special behavior, see split: "any leading whitespace in EXPR is removed before splitting occurs, and the PATTERN is instead treated as if it were /\s+/; in particular, this means that any contiguous whitespace (not just a single space character) is used as a separator.". | [reply] [d/l] [select] |
Re: Array of variables
by 1nickt (Canon) on Apr 27, 2017 at 15:46 UTC
|
$Variables[$X]=$Year."-".$Months{$Month} ."-" . $Day ;
Also see sprintf for formatting text strings (e.g.: $Day = sprintf('%02d', $Day);)
But really you should avoid manipulating dates by hand. There are plenty of modules that do it better, faster and more safely. See for example DateTime::Format::Strptime. This will give you a tool to read in a date using whatever format you have it in, transform it in some way if desired, and print it out again in a different format. For example:
use strict; use warnings; use feature 'say';
use DateTime::Format::Strptime;
my $date = 'Apr 23 2017 11:56:42';
my $parser = DateTime::Format::Strptime->new( pattern => '%b %d %Y %T'
+, on_error => 'croak' );
my $dt = $parser->parse_datetime( $date );
say $dt->strftime('%F');
Output:
2017-04-23
Hope this helps!
Update: Added DT and sprintf examples
The way forward always starts with a minimal test.
| [reply] [d/l] [select] |
|
|
i tried that technique previously didn't work
Step 1: load variables from sql call from database
Step 2: placed variable into an array
Step 3: process data in current array, formatting date to html date field format
Step 4: reload the new back back into the variable that is in the array
issue do not know how to address an array of variable to place the data back into the array variable
$Variables$X = ( $Map_Request_Date,$Map_Due_Date,$Map_Cutover_Date,$Map_Complete_Date,$Map_Approved_Date);
| [reply] |
|
|
@Variables = ( $Map_Request_Date, $Map_Due_Date, $Map_Cutover_Date, $M
+ap_Complete_Date, $Map_Approved_Date );
But again, this is no way to accomplish your task.
Also, please use <code></code> tags for even the shortest code snippets: as you can see, in both your posts the square brackets used to denote array indices are not showing. This is because the posting engine treats them as something else because they are not in code tags.
The way forward always starts with a minimal test.
| [reply] [d/l] [select] |
Re: Array of variables
by shmem (Chancellor) on Apr 28, 2017 at 09:09 UTC
|
There is no such thing as an "Array of variables". This
my @Variables = ( $Map_Request_Date,$Map_Due_Date,$Map_Cutover_Date,$M
+ap_Complete_Date,$Map_Approved_Date);
does not do what you think it does. You are assigning the contents of those variables to a new array, not the variables themselves. In the loop you are modifying the values in the array, not the original variables:
my($foo, $bar) = (1,2);
my @vars = ($foo, $bar);
foreach my $var (@vars) {
$var += 4;
}
print "\@vars: @vars\n";
print "\$foo: $foo\n";
print "\$bar: $bar\n";
__END__
@vars: 5 6
$foo: 1
$bar: 2
Is that what you want to do? Or do you want to modify the values in the variables? In that case, you have two possibilities:
- use the list of variables as argument to the foreach loop:
my($foo, $bar) = (1,2);
foreach my $var ($foo, $bar) {
$var += 4;
}
print "\$foo: $foo\n";
print "\$bar: $bar\n";
__END__
$foo: 5
$bar: 6
The loop variable $var is an alias for each item in the list. The same happens if you iterate over an array: the loop variable is then an alias to each slot in the array.
- take references to the original variables:
my($foo, $bar) = (1,2);
my @vars = \($foo, $bar); # note the backslash before the list
# this would do the same: my @vars = (\$foo, \$bar);
foreach my $var (@vars) {
$$var += 4; # note the de-referencing $ before $var
}
print "\@vars: @vars\n";
print "\$foo: $foo\n";
print "\$bar: $bar\n";
__END__
@vars: SCALAR(0x15ae7a0) SCALAR(0x15ae830)
$foo: 5
$bar: 6
In this case, the @vars array is populated with references to the original variables, which are values. To modify what they point at, they must be de-referenced. Doing so gives access to the body of the variable of which the reference has been taken.
Almost always the first way is used.
Then, your %Months hash only holds constants, but you are setting it up and tearing it down everytime through the loop. Move that outside the loop. You can limit the scope of that hash by wrapping all into a bare block:
{
my %Months = (...);
...
foreach $var (...) {
...
}
}
# %Months not defined here anymore
Lastly, it is easier to reformat your date strings using split and sprintf:
my %Months = (Dec => 12);
my $date = 'Dec 1 2016 18:15';
my @pcs = split " ", $date;
$date = sprintf "%02d %02d %d %s",$Months{$pcs[0]}, @pcs[1..3];
print "date: '$date'\n";
__END__
date: '12 01 2016 18:15'
The construct @pcs[1..3] is an array slice of @pcs from index 1 to 3.
update: add/fix links
perl -le'print map{pack c,($-++?1:13)+ord}split//,ESEL'
| [reply] [d/l] [select] |
Re: Array of variables
by thanos1983 (Parson) on Apr 27, 2017 at 20:46 UTC
|
Hello Michael W,
It seems the fellow monks have already resolve your issue, but I found some relative information and I thought it would be nice to share.
First I would suggest to read a similar question (dbi and dates).
There is also another suggestion of creating your own function and return unix timestamp, where from there you can literally do what ever you want. According to this post (UNIX_TIMESTAMP in SQL Server).
Hope this helps.
Seeking for Perl wisdom...on the process of learning...not there...yet!
| [reply] [d/l] |
Re: Array of variables
by Laurent_R (Canon) on Apr 28, 2017 at 06:17 UTC
|
What do you mean exactly with "array of variables"?
I'm asking because using such a term seems to indicate some form of misunderstanding. Arrays are variable but they really contain values, not variables. Of course, those values can be references to other variables, but they are still only values, not variables.
| [reply] |
Re: Array of variables
by kcott (Archbishop) on Dec 14, 2021 at 20:58 UTC
|
Note:
This was an accidental reply to "Array of variables" which was originally posted in April 2017.
It was suggested by ++jdporter that I consider it for re-parenting.
[See "Re^5: Array of variables" for an explanation of the striking of the "Note:".]
G'day Michael W,
To my mind, the following is cleaner, more readable, and more maintainable.
Here's the basic changes:
-
Moved the static data out of the loop: doesn't need to be redefined on every iteration.
-
Reused the test data from choroba's 3rd code example.
-
Made the elements of the array actual references.
You used $Date_Ref which is poorly named because they're strings, not references.
-
The loop now just contains two statements: much easier to read and maintain.
#!/usr/bin/env perl
use strict;
use warnings;
my %months;
@months{qw{Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec}}
= '01' .. '12';
my $out_fmt = '%4d-%s-%02d';
my ($Map_Request_Date,
$Map_Due_Date,
$Map_Cutover_Date,
$Map_Complete_Date,
$Map_Approved_Date
) = (
'Jan 1 2017 12:00',
'Jan 31 2017 12:00',
'Feb 28 2017 23:59',
'Mar 1 2017 12:01',
'Dec 31 1999 0:01'
);
my @var_refs = \(
$Map_Request_Date,
$Map_Due_Date,
$Map_Cutover_Date,
$Map_Complete_Date,
$Map_Approved_Date
);
print "$$_\n" for @var_refs;
for (@var_refs) {
my ($m, $d, $y, undef) = split ' ', $$_;
$$_ = sprintf $out_fmt, $y, $months{$m}, $d;
}
print "$$_\n" for @var_refs;
Output:
Jan 1 2017 12:00
Jan 31 2017 12:00
Feb 28 2017 23:59
Mar 1 2017 12:01
Dec 31 1999 0:01
2017-01-01
2017-01-31
2017-02-28
2017-03-01
1999-12-31
Update:
It looks like I mis-clicked on your last post instead of your current post, and replied to that.
Hopefully, there's still some useful information.
[See "Re^5: Array of variables" for some more details about that.]
| [reply] [d/l] [select] |
|
|
| [reply] |
|
|
| [reply] |
|
|
|
|
|
|
| [reply] |
|
|
| [reply] |