in reply to sorting tree with folders on top

Using Sort::Key:

(Note that this code really does a natural sort inside the path parts so, for instance, "a2" goes before "a12")

use Sort::Key::Natural qw(mkkey_natural); use Sort::Key qw(keysort); my @arr = ( { 'path' => '/c/', dir => '/' }, { 'path' => '/c/a1.mp3', 'file' => 1, 'dir' => '/c' }, { 'path' => '/c/a2.mp3', 'file' => 1, 'dir' => '/c' }, { 'path' => '/c/bb/aa1.mp3', 'file' => 1, 'dir' => '/c' }, { 'path' => '/c/bb/aa2.mp3', 'file' => 1, 'dir' => '/c' }, { 'path' => '/c/bb/aa12.mp3', 'file' => 1, 'dir' => '/c' }, { 'path' => '/c/bb/', 'dir' => '/c' }, { 'path' => '/c/cc/', 'dir' => '/c' }, { 'path' => '/c/aa/', 'dir' => '/c' } ); sub mkkey_fspath { my $path = shift; join("\x00/", map(mkkey_natural($_), split(/\/+/, $path))) } my @arr = keysort { if ($_->{file}) { my ($dir, $file) = $_->{path} =~ m|^((?:.*/)?)([^/]*$)|; join("\x01/", mkkey_fspath($dir), mkkey_fspath($file)); } else { my $dir = $_->{path}; $dir =~ s|/+$||; mkkey_fspath($dir); } } @arr; foreach (@arr) { my %h = %{$_}; print $h{'path'}."\n"; }
update: as diweooy pointed out there was an error on the key generation sub.

Replies are listed 'Best First'.
Re^2: sorting tree with folders on top
by diweooy (Novice) on Apr 07, 2009 at 11:48 UTC
    output:
    /c/ /c/aa/ /c/bb/ /c/cc/ << this should be below /c/bb/*.mp3 /c/bb/aa1.mp3 /c/bb/aa2.mp3 /c/bb/aa12.mp3 /c/a1.mp3 /c/a2.mp3
    it looks better on the first look, but /c/bb/*.mp3 should be below /c/bb, not below /c/cc.
        thanks, but I get a list of paths in a file. I have no influence on the (creation of the) list.