package Language::MySort; require Exporter; @ISA = qw( Exporter ); @EXPORT = qw( lang sort ); %words = (); sub lang_sort { my ($ignore, $same, $chars, $tr, $sorter) = ("", ""); if (ref $_[-1]) { my $opt = pop; $ignore = $opt->{ignore} || ""; $same = $opt->{translate} || ""; $ignore = "\$s =~ tr/\Q$ignore\E//d;"; if ($same) { my @f = map substr($_, 0, 1, ""), @$same; $same = " =~ tr/" . quotemeta(join "", @$same) . "/" . quotemeta(join "", map $f[$_] x length($same->[$_]), 0 .. $#$same) . "/"; } } $chars = @_ == 1 ? shift : join "", @_; $tr = eval qq{ sub { (my \$s = shift) $same; $ignore \$s =~ tr/\Q$chars\E/\000-\377/; \$s; } }; $sorter = sub { my @used = map $tr->($_), @_; @{ $words{$chars} }{ @used } = @_; @{ $words{$chars} }{ sort @used }; }; return wantarray() ? ($sorter, $tr) : $sorter; } 1; #### use Language::MySort; *french_sort = lang_sort( # *the character list* # only includes the characters remaining after # the identical-character map has been applied 'a' .. 'z', { # *the identical-character map* # maps characters to the character # they should sort identically as # "AXYZ" means that X, Y, and Z are translated as A identical => ["a\340", "c\347", "e\350\351\352\353", "o\364"], } ); { local $, = " "; print french_sort( "\351tude", "\352tre", "tr\350s", "entrer", "\351t\351", ); } #### use Language::MySort; *weird_sort = lang_sort( # place vowels ahead of consonants qw( a e i b c d f g h j ), { # map uppercase characters to lowercase identical => [qw( aA bB cC dD eE fF gG hH iI jJ )], # ignore - and . ignore => "-.", } ); #### use Language::MySort; *weird_sort = lang_sort( # place vowels ahead of consonants qw( a e i ), 'a' .. 'j', { # map uppercase characters to lowercase identical => [qw( aA bB cC dD eE fF gG hH iI jJ )], # ignore - and . ignore => "-.", } ); #### use Language::MySort; *sorter = lang_sort( # nifty way to make (A, a, B, b, C, c, ... Z, z) (map +($_, lc), 'A' .. 'Z') { ignore => q{-} } );