Win has asked for the wisdom of the Perl Monks concerning the following question:

This node falls below the community's minimum standard of quality and will not be displayed.

Replies are listed 'Best First'.
Re: Working with a unknown number of arrays
by davorg (Chancellor) on Feb 05, 2007 at 16:42 UTC
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Working with a unkown number of arrays
by jdporter (Paladin) on Feb 05, 2007 at 17:14 UTC

    I think you're definitely on the track, to want to generalize the code to any number of directories. The first thing to do is try to eliminate variables — or rather, variable names — which perpetuate the "one chunk of code per directory" mentality.

    Below is how you might reduce it to a loop.

    sub Prioritise_requests { my( $input_directory, $node ) = @_; for my $dir_num ( '1', '2', '3' ) { my $input_dir = $input_directory.$dir_num; opendir DIR, $input_dir or die "Error opening directory $input_dir + - $!"; my @files = sort { -M $a <=> -M $b } map "$input_dir/$_", grep /^Flat_file.*\.txt$/, readdir DIR; closedir DIR; foreach ( @files ) { if ( Is_the_file_mine($node, $_) and Do_I_run_the_request_now($_ +) ) { move $_, $input_directory or warn "Error moving $_ to $input_d +irectory - $!"; return; } } } }

    I've also made one critical bug fix in the code above: You have to add the directory name to the file name before you get any of the file's information, e.g. -M.

    Also, I made a change as to the assumed return values of the two hypothetical subroutines Is_the_file_mine and Do_I_run_the_request_now. You were assuming they'd return characters. But really, they return boolean (true/false) conditions. May as well just code for that directly.

    A word spoken in Mind will reach its own level, in the objective world, by its own weight
    A reply falls below the community's threshold of quality. You may see it by logging in.
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Working with a unkown number of arrays
by wojtyk (Friar) on Feb 05, 2007 at 17:02 UTC
    You've gone about this problem in a somewhat ugly manner (it appears as if you cut and pasted the same code 3 times). A more elegant solution would store everything in a hash with the priority level included. So each priority value would be a key and file (or directory) would be a value (or vice versa). Then you could just sort by hash key/value. Pseudo-code:
    sub Prioritise_requests { my ($input_directory, $node) = @_; my %files; $files{1} = $input_directory."1"; $files{2} = $input_directory."2"; $files{3} = $input_directory,"3"; # this is looping on the directories in a prioritized manner foreach (sort keys %files) { open(*DATA,$_) or die; # this is looping through each file you want in each directory foreach (sort grep(/^Flat_file.*\.txt$/,readdir(DATA))) { # do your stuff for each file } close(DATA); } }
      Hi, I understand that what you wrote is marked as "pseudocode", but I noticed a couple of strange things:
      $files{3} = $input_directory,"3";
      Maybe you meant to put a dot "." instead of a comma ","?

      Another thing that I don't understand from this fragment is if %files holds filenames or directory names. The use of open() and close() seems to point to "filenames", but in this case the readdir(DATA) should be simply <DATA>.

      Regarding the open(), at the price of backward compatibility with 5.6, I use lexical filehandles instead of barewords:

      open my $data, ...
      Moreover, I usually stick to the three argument version of open(), not because this is requested by this particular application (I actually don't know), but more for sake of a mental habit (yes, I'm mental :) :
      open my $data, '<', $files{$_} ...
      I find it better not only because it avoids nasty problems when the filename comes from the "untrusted external" (which could lead to embarassing security holes), but also because it visually marks that this open is for read instead of write.

      Last, even if the plain die does the work (especially in pseudocode!), it could be helpful to provide a more sensible feedback message, either directly:

      open my $data, '<', $files{$_} or die "open('$files{$_}'): $!";
      or with
      use Fatal qw( open );
      in the script's preamble.

      Forgive me for jumping on your shoulders this way, but the OP seems to have some bias towards blind cut-and-paste, you know, so it could be useful for her|him to think about these issues ;)

      Flavio
      perl -ple'$_=reverse' <<<ti.xittelop@oivalf

      Don't fool yourself.

        Regarding the open(), at the price of backward compatibility with 5.6, I use lexical filehandles instead of barewords:

        Lexical handles (and 3-arg open) work fine in 5.6.

        >c:\progs\perl560\bin\perl script.pl open(my $data, '<', $0) or die; print while <$data>;

        Lexical handles were introduced in 5.6, so you are sacrificing backwards compatibility wih 5.5 (5.005).

        What was introduced in 5.8 is file handles to variables (open(my $fh, '<', \$buf)).

        Heh, no worries. I wasn't exactly trying to meet stellar code standards. It was the best I could spit out in about 30-40 seconds ;)
      That open(DATA) line should be:
      open(*DATA,$files{$_}) or die;
      You get the point though.
Re: Working with a unkown number of arrays
by jdporter (Paladin) on Feb 05, 2007 at 17:00 UTC

    Question: In the code above, you only do anything (processing files in any folder) if there is something in the high-priority folder. Specifically, you have:

    if (@sorted_highest_priority) { foreach (@sorted_highest_priority){ ... } if (@sorted_middle_priority) { foreach (@sorted_middle_priority){ ... } } if (@sorted_lowest_priority) { foreach (@sorted_lowest_priority){ ... } } }

    That's a mistake, right?

    A word spoken in Mind will reach its own level, in the objective world, by its own weight
    A reply falls below the community's threshold of quality. You may see it by logging in.
Re: Working with a unkown number of arrays
by Moron (Curate) on Feb 05, 2007 at 17:28 UTC
    Files of lower priority are unprocessed, so the finding can be cut short when files are found in a higher folder.e.g.
    my @folders = glob 'input_directory*'; # get/sort all qualifying folde +rs my @requests; for (my ($found, %filedate); $found = pop @folders or exit();) { @requests = sort { { ( $filedate{ $a } ||= -M $a ) <=> ( $filedate{ $b } ||= -M $b ) } glob "$found/" . 'Flat_file.*.txt' and last; # reiterate iff none found }
    If the loop completes having found @requests, they will have been selected from the highest non-empty qualifying directory and be sorted by creation/modification date. (updated)

    -M

    Free your mind

Re: Working with a unkown number of arrays
by GrandFather (Saint) on Feb 05, 2007 at 20:54 UTC

    A hash of prioritised lists seems like what you need:

    use warnings; use strict; my $inputdir; my %files = Prioritise_requests ($inputdir); for my $fileList (sort keys %files) { print "$files{$file}->[0]\n"; # Lowest priority file print "$files{$file}->[-1]\n"; # Top priority file } sub Prioritise_requests { my ($input_directory, $node) = @_; my %files; my $index = 1; while (1) { last if ! opendir SCAN, "$input_directory$index"; for my $filePath (grep (/^Flat_file.*\.txt$/, readdir (SCAN))) + { my ($file) = $filePath =~ m![^\\/]*$!; push @{$files{$file}}, $_; ++$index; } closedir SCAN; } return %files; }

    Note that this is untested and doesn't include all the "non-issue" work of your sample code.

    Updated to avoid "perpetual" loop


    DWIM is Perl's answer to Gödel
    A reply falls below the community's threshold of quality. You may see it by logging in.