in reply to A hash of a range of another hash

Hi all,

Thanks for the input!

The following is the answer I was looking for and was provided by an Anonymous Monk.
Thank you!

my (%r) = map { $_ => $f{$_} } $left .. $right;

And what I am doing!
"Brain Cell Exercise Project 11"

#!/usr/bin/perl # # BCE Project 11 # use strict; use warnings; my $Directory = '/usr/bin'; # Any directory containing files will do my %Fhash; # Numbered file list hash my @Farray; # Array of found files my $Itemcount = 0; # Count of files found my $File; # my $Pagelen = 20; # Page length (Number of items to print) my $Input; # sub printlist { my %Thash; my $Start = $_[0]; my $End = $_[1]; my $Item; if ($End > $Itemcount) { $End = $Itemcount; } %Thash = map { $_ => $Fhash{$_} } $Start .. $End; foreach $Item (sort{$a <=> $b} keys %Thash) { printf "%s :%s\n", $Item, $Thash{$Item}; } } opendir(DIR, $Directory) || die "can't opendir $Directory: $!"; @Farray = grep { -f "$Directory/$_" } readdir(DIR); closedir DIR; # Create serialized hash of the files... foreach $File (sort sort{$b cmp $a} @Farray) { $Fhash{ ++$Itemcount } = "$Directory/$File"; } print "Itemcount=", $Itemcount, "\n"; while (1) { print "Enter number: "; my $Input = <STDIN>; chomp $Input; if ( $Input =~ m/^q/ ) { # q to quit last; } printlist $Input, $Input + $Pagelen - 1; }

Ultimately the goal is to page (or line by line) up and down through the list, and enter a number to select a file.
Just have not gotten that far yet.

This is a Brain Cell Exercise so, Any pointers to cleaner, neater, slicker methods would be VERY WELCOME and will be appreciated!

-Enjoy
fh : )_~

Replies are listed 'Best First'.
Re^2: A hash of a range of another hash
by CountZero (Bishop) on Sep 12, 2009 at 14:29 UTC
    What do you think of this?
    #!/usr/bin/perl # # BCE Project 11 # use strict; use warnings; my $Directory = 'c:/data'; # Any directory containing files will do my @Farray; # Array of found files my $Pagelen = 20; # Page length (Number of items to print) sub printlist { my ( $Start, $End, @array ) = @_; $End = $End > @array ? @array : $End; printf "%s: %s\n", $_, $array[ $_ - 1 ] foreach $Start .. $End ; } ## end sub printlist opendir( DIR, $Directory ) || die "can't opendir $Directory: $!"; @Farray = sort grep { -f "$Directory/$_" } readdir(DIR); closedir DIR; print "Itemcount= scalar @Farray\n"; while (1) { print "Enter number: "; my $Input = <STDIN>; last if $Input =~ m/^q/i; printlist $Input, $Input + $Pagelen - 1, @Farray; } ## end while (1)

    To start with we have done away with the hash-based storage of the filenames. The result of the grep is sorted and directly stored in an array.

    The while loop has been cleaned-up as well: no need to chomp your input here. Perl is not bothered by the "\n" at the end of the input when used in numerical context.

    I have used a statement modifier rather than an if .. then ... construct for the last in the loop. Personally I find it clearer and more expressive, but that is just a personal thing.

    The subroutine call now adds the array with the filenames at the end of the parameter list. Together with some other changes in the printlist subroutine it means that the subroutine does not rely on any variables which exist outside of itself. This is something I have found to be very handy: now the subroutine can be used anywhere in your program or --if put in a librarymodule-- even in other programs. Also, there is now no "action at a distance" possible: otherwise a certain source of difficult to trace bugs!

    The printlist subroutine is now very simple: it uses no variables other than those necessary to store its parameters. The ... ? ... : ... construct is a very compact way of putting boundaries on the value of a variable and if necessary it can be nested if more conditions need to be checked.

    Note that the array index needs to be reduced by one, as arrays are zero-based and your program uses a one-based approach.

    The program still has room for improvement: for instance if a really huge array of filenames needs to be processed, then it will be faster and less memory intensive if rather than the array itself, only a reference to the array is put in the parameter list. Of course you will have to dereference this array-reference where needed in the printlist subroutine! For small arrays (up to many thousands of elements), there is not really a big benefit in doing so however.

    CountZero

    A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James