How would I know if there is any similar element in my array?
I have this code which lists all files in my directory:
$dir = '/var/www/corpIDD/rawFile/';
opendir DIR, $dir or die "cannot open dir $dir: $!";
my @file= readdir DIR;
closedir DIR;
which returns an array containing something like this:
开发者_如何学Python$array (0 => 'ipax3_2011_01_27.txt', 1 => 'ipax3_2011_02_01.txt', 2 => 'ipax3_2011_02_03.txt')
My problem here is, how will I store elements 1 => 'ipax3_2011_02_01.txt' and 2 => 'ipax3_2011_02_03.txt' to separate variable as they belong to the same month and year(2011_02)?
Thanks!
In Perl, when you need to use a string as the key in a data structure, you are looking for the HASH
builtin type, designated by the %
sigil. A nice feature of Perl's hashes is that you do not have to pre-declare a complex data structure. You can use it, and Perl will infer the structure from that usage.
my @file = qw(ipax3_2011_01_27.txt ipax3_2011_02_01.txt ipax3_2011_02_03.txt);
my %ipax3;
for (@file) {
if (/^ipax3_(\d{4}_\d{2})_(\d{2}).txt$/) {
$ipax3{$1}{$2} = $_
}
else {
warn "bad file: $_\n"
}
}
for my $year_month (keys %ipax3) {
my $days = keys %{ $ipax3{$year_month} };
if ($days > 1) {
print "$year_month has $days files\n";
}
else {
print "$year_month has 1 file\n";
}
}
which prints:
2011_01 has 1 file 2011_02 has 2 files
To get at the individual files:
my $year_month = '2011_02';
my $day = '01';
my $file = $ipax3{$year_month}{$day};
Above I used the return value of the keys
function as both the list to iterate over, and as the number of days. This is possible because keys
will return all of the keys when in list context, and will return the number of keys in scalar context. Context is provided by the surrounding code:
my $number = keys %ipax3; # number of year_month entries
my @keys = keys %ipax3; # contains ('2011_01', '2011_02')
my @days = keys %{ $ipax{$year_month} };
In the last example, each value in %ipax
is a reference to a hash. Since keys
takes a literal hash, you need to wrap $ipax{$year_month}
in %{ ... }
. In perl v5.13.7+ you can omit the %{ ... }
around arguments to keys
and a few other data structure access functions.
People are responding really fast here :) anyway, I'll post mine, just for your reference. Basically, I'm also using a hash.
use warnings qw(all);
use strict;
my ($dir, $hdir) = 'C:\Work';
opendir($hdir, $dir) || die "Can't open dir \"$dir\" because $!\n";
my (@files) = readdir($hdir);
closedir($hdir);
my %yearmonths;
foreach(@files)
{
my ($year, $month);
next unless(($year, $month) = ($_ =~ /ipax3_(\d{4})_(\d{2})/));
$year += 0;
--$month; #assuming that months are in range 1-12
my $key = ($year * 12) + $month;
++$yearmonths{ $key };
}
foreach(keys %yearmonths)
{
next if($yearmonths{ $_ } < 2);
my $year = $_ / 12;
my $month = 1 + ($_ % 12);
printf "There were %d files from year %d, month %d\n", $yearmonths{$_}, $year, $month;
}
精彩评论