Reputation: 2955
I am reading an ordered file for which I must count by-hour, by-minute or by-second occurrences. If requested, I must print times with 0 occurrences (normalized output) or skip them (non-normalized output). The output must obviously be ordered.
I first thought using an array. When the output is non normalized, I am doing roughly the equivalent of:
@array[10] = 100;
@array[10000] = 10000;
And to print the result:
foreach (@array) {
print if defined;
}
Is there a way to reduce iterations to only elements defined in the array? In the previous example, that would mean doing only two iterations, instead of 10000 as using $#array
implies. Then I would also need a way to know the current array index in a loop. Does such a thing exist?
I am thinking more and more to use a hash instead. Using a hash solves my problem and also eliminates the need to convert hh:mm:ss times to index and vice-versa.
Or do you have a better solution to suggest for this simple problem?
Upvotes: 1
Views: 254
Reputation: 241808
You can also remember just the pairs of numbers in an array:
#!/usr/bin/perl
use warnings;
use strict;
my @ar = ( [ 10, 100 ],
[ 100, 99 ],
[ 12, 1 ],
[ 13, 2 ],
[ 15, 1 ],
);
sub normalized {
my @ar = sort { $a->[0] <=> $b->[0] } @_;
map "@$_", @ar;
}
sub non_normalized {
my @ar = sort { $a->[0] <=> $b->[0] } @_;
unshift @ar, [0, 0] unless $ar[0][0] == 0;
my @return;
for my $i (0 .. $#ar) {
push @return, "@{ $ar[$i] }";
push @return, $_ . $" . 0 for 1 + $ar[$i][0] .. $ar[$i + 1][0] - 1;
}
return @return;
}
print join "\n", normalized(@ar), q();
print "\n";
print join "\n", non_normalized(@ar), q();
Upvotes: 2
Reputation: 20131
Yes, use a hash. You can iterate over the ordered array of the keys of the hash if your keys sort correctly.
Upvotes: 6