Capitalismczar
Capitalismczar

Reputation: 31

Dynamic Array Inside a Foreach Loop

First time poster and new to Perl so I'm a little stuck. I'm iterating through a collection of long file names with columns separated by variable amounts of whitespace for example:

0     19933     12/18/2013 18:00:12  filename1.someextention
1     11912     12/17/2013 18:00:12  filename2.someextention
2     19236     12/16/2013 18:00:12  filename3.someextention

These are generated by multiple servers so I am iterating through multiple collections. That mechanism is simple enough.

I'm focused solely on the date column and need to ensure the date is changing like the above example as that ensures the file is being created on a daily basis and only once. If the file is created more than once per day I need to do something like send an email to myself and move on to the next server collection. If the date changes from the first file to the second exit the loop as well.

My issue is I don't know how to keep the date element of the first file stored so that I can compare it to the next file's date going through the loop. I thought about keeping the element stored in an array inside the loop until the current collection is finished and then move onto the next collection but I don't know the correct way of doing so. Any help would be greatly appreciated. Also, if there is a more eloquent way please enlighten me since I am willing to learn and not just wanting someone to write my script for me.

@file = `command -h server -secFilePath $secFilePath analyzer -archive -list`;
@array = reverse(@file); # The output from the above command lists the oldest file first 

    foreach $item (@array) {
    @first = split (/ +/, @item);
    @firstvar = @first[2];
#if there is a way to save the first date in the @firstvar array and keep it until the date
 changes       
    if @firstvar == @first[2] { # This part isnt designed correctly I know.                }
            elsif @firstvar ne @first[2]; {
            last;
            }
}

Upvotes: 3

Views: 641

Answers (1)

rutter
rutter

Reputation: 11452

One common technique is to use a hash, which is a data structure mapping key-value pairs. If you key by date, you can check if a given date has been encountered before.

If a date hasn't been encountered, it has no key in the hash.

If a date has been encountered, we insert 1 under that key to mark it.

my %dates;
foreach my $line (@array) {
    my ($idx, $id, $date, $time, $filename) = split(/\s+/, $line);

    if ($dates{$date}) {
        #handle duplicate
    } else {
        $dates{$date} = 1;

        #...
        #code here will be executed only if the entry's date is unique
    }

    #...
    #code here will be executed for each entry
}

Note that this will check each date against each other date. If for some reason you only want to check if two adjacent dates match, you could just cache the last $date and check against that.


In comments, OP mentioned they might rather perform that second check I mentioned. It's similar. Might look like this:

#we declare the variable OUTSIDE of the loop
#if needs to be, so that it stays in scope between runs
my $last_date;
foreach my $line (@array) {
    my ($idx, $id, $date, $time, $filename) = split(/\s+/, $line);

    if ($date eq $last_date) { #we use 'eq' for string comparison
        #handle duplicate
    } else {
        $last_date = $date;

        #...
        #code here will be executed only if the entry's date is unique
    }

    #...
    #code here will be executed for each entry
}

Upvotes: 3

Related Questions