At 3:03 PM -0400 10/21/02, Akens, Anthony wrote:
>I'm attempting to use the following code to read a file
>in the format of:
>
>directory name:displayname
>
>I want to sort the list by the "displayname", looking
>at the first letter for each display name in the file.
>If it's unique, I want to print it.  This should result
>in an alphabetical list of the letters for the display
>names.  However, the sort is not working quite right,
>and I sometimes get letters out of order, missing, or
>some that aren't even in the list.
>
>Can anyone tell me what I've done wrong?

        First of all, it looks like you are sorting based on directory
name, not on the "displayname", since you are sorting on the keys and the
keys are the first part of the 'split /:/'.

        The second thing, is that you are only saving one value per
'directory name' -- if there is more than one file (assuming 'displayname'
is the name of a file) in a directory, then you will only get the last file
because your '$Names{$key} = $value;' is overwriting the previous value.

        If all you want is the list of unique letters that all the files
start with, then you'd probably be better off with something much simpler,
such as:

-------------------------------------------------------------------

while (<NAMES>) {
        ($dir, $file) = split /:/;
        $letter = uc(substr($file, 0, 1));
        $letters{$letter} = 1; # or $letters{$letter}++; to track the number
}

print "<P>";

foreach $letter (sort keys %letters) {
    print "<A HREF=\"\#$letter\">$letter<\/a> ";
}

-------------------------------------------------------------------


        If you want to retain the list of files and the directory they are
in and have them sorted by the displayname, then I'd do something like this
(this assumes that the file names are case sensitive so we need to retain
the case but we want the sort to be case insensitive):

-------------------------------------------------------------------

while (<NAMES>) {
        ($dir, $file) = split /:/;
        $letter = uc(substr($file, 0, 1));
        push(@{$files{$letter}}, [lc($file), $file, $dir])
}

#
# %files is now a hash array with keys that are the uppercase first letter
# of the file names and the values are array references
#
# Each array reference contains array references which contain
# the file name in lower case, the file name in the original case,
# and the dir name in the [0] and [1] positions
#

print "<P>";

# print out the index
foreach $letter (sort keys %files) {
    print "<A HREF=\"\#$letter\">$letter<\/a> ";
}

# print out the file list
foreach $letter (sort keys %files) {
        print "<h2><a name=\"$letter\">$letter</a></h2>\n";

        foreach $file_ref (sort {$a->[0] cmp $b->[0]} @{$files{$letter}}) {
                print "$file_ref->[2]:$file_ref->[1]<br>\n";
        }
}

-------------------------------------------------------------------

        Note that the conversion to upper or lower case only occurs once
when we are saving the file info. If you do the conversion in the sort
block, perl may end up doing the conversion on every comparison (unless it
caches the comparison values which it may well do). This comes at the
expense of having to save the converted filename, so if for some reason you
are tight on memory (i.e. 1000s of filenames) and have lots of CPU cycles
to spare, then you might not want to save it and do the case conversion in
the sort block.

        There are, of course, lots of variations on this that will work
just as well!

        ---Larry




+------------------------------------------------------------------------+
| Larry Coffin, G.P.H.                                     Watertown, MA |
| http://www.PointInfinity.com/lcoffin/        [EMAIL PROTECTED] |
+------------------------------------------------------------------------+

Demographic polls show that you have lost credibility across the
board.  Especially with  those 14 year-old Valley girls.


-



-- 
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to