Jemand zu Hause?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
#!/usr/bin/perl use strict; use warnings; use Encode qw(decode); use Unicode::Collate; use String::Random; my $zeilen = 10000; my $spalten = 5; my $methode = 2; ####################################### my %data; for (my $z = 0; $z < $zeilen; $z ++) { my @felder; for (my $s = 0; $s < $spalten; $s ++) { my $d = String::Random::random_string( '10101022',[ split //, uc 'aei' ],[ split //, uc 'bdfghklmnprstwxz' ],[ split //, '23456789' ]); push @felder,$d; # print " $d"; } push @{$data{spalten}},[@felder]; # print "\n"; } print "Daten fertig erzeugt\n"; ####################################### print "\n\nSortiert:\n"; if ($methode == 1) { my $start = time(); my $uniccol = Unicode::Collate->new(); foreach my $harefz ( sort { my $return = 0; my $z = -1; while (!$return && $z < scalar @{$data{spalten}} - 1) { $z ++; $return = $uniccol->cmp($a->[$z],$b->[$z]); } $return; } @{$data{spalten}} ) { for (my $s = 0; $s < scalar @{$harefz}; $s ++) { # print ' '.$harefz->[$s]; } # print "\n"; } print "\nLaufzeit: ".(time()-$start); } else { my $start = time(); foreach my $harefz ( sort { my $return = 0; my $z = -1; while (!$return && $z < scalar @{$data{spalten}} - 1) { $z ++; $return = lc $a->[$z] cmp lc $b->[$z]; } $return; } @{$data{spalten}} ) { for (my $s = 0; $s < scalar @{$harefz}; $s ++) { # print ' '.$harefz->[$s]; } # print "\n"; } print "\nLaufzeit: ".(time()-$start); }
Unicode::Collate läuft bei diesen Mengen auf meinem Rechner 14 Sekunden und mit lc weniger als eine volle Sekunde. Wobei
Unicode::Collate natürlich korrekt sortiert und lc nicht.1 2 3
my $uniccol = Unicode::Collate->new(); my @s = sort { $uniccol->cmp($a,$b) } ('Vertrag','Übel','Ärger','Öl','ßig','ärgerlich'); print join(' + ',@s);
1 2
my $uniccol = Unicode::Collate->new(); print join(' + ',sort {$a =~ /[öäüßÖÄÜ]/ || $b =~ /[öäüÄÖÜß]/ ? $uniccol->cmp($a,$b) : lc $a cmp lc $b} ('Vertrag','Übel','Ärger','Öl','ßig','ärgerlich'));
2014-12-28T16:29:05 reneeVielleicht hilft bei Dir ja auch "use locale": http://perldoc.perl.org/locale.html
QuoteRenee + Renée + Vertrag + Ärger + Öl + Übel + ßig + ärgerlich
Unicode::Collate?
2014-12-28T16:29:05 reneeIn Robins Blog wurde ja auf https://github.com/tonycoz/Unicode-ICU/tree/master... hingewiesen was schneller sein soll.
Quotecpan> install Unicode::ICU::Collator
Fetching with LWP:
http://cpan.strawberryperl.com/authors/01mailrc.tx...
Fetching with LWP:
http://cpan.strawberryperl.com/modules/02packages....
Fetching with LWP:
http://cpan.strawberryperl.com/modules/03modlist.d...
Database was generated on Thu, 25 Dec 2014 16:21:57 GMT
Updating database file ...
Done!Running install for module 'Unicode::ICU::Collator'
Running make for T/TO/TONYC/Unicode-ICU-Collator-0.002.tar.gz
Fetching with LWP:
http://cpan.strawberryperl.com/authors/id/T/TO/TON...
Fetching with LWP:
http://cpan.strawberryperl.com/authors/id/T/TO/TON...
Checksum for C:\strawberry\cpan\sources\authors\id\T\TO\TONYC\Unicode-ICU-Collator-0.002.tar.gz ok
Scanning cache C:\strawberry\cpan\build for sizes
............................................................................DONE
CPAN.pm: Building T/TO/TONYC/Unicode-ICU-Collator-0.002.tar.gz
Der Befehl "icu-config" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.
OS unsupported: No icu-config --cppflags found
Warning: No success on command[C:\strawberry\perl\bin\perl.exe Makefile.PL]
TONYC/Unicode-ICU-Collator-0.002.tar.gz
C:\strawberry\perl\bin\perl.exe Makefile.PL -- NOT OK
Running make test
Make had some problems, won't test
Running make install
Make had some problems, won't install
Stopping: 'install' failed for 'Unicode::ICU::Collator'.
Could not read metadata file. Falling back to other methods to determine prerequisites
Failed during this command:
TONYC/Unicode-ICU-Collator-0.002.tar.gz : writemakefile NO 'C:\strawberry\perl\bin\perl.exe Makefile.PL' returned status 256
Encode:1 2
use Encode qw(encode decode); print encode('iso-8859-15',join(' + ',sort {lc $a cmp lc $b} ('Vertrag',decode('windows-1252','Übel'),decode('windows-1252','Ärger'),decode('windows-1252','Renée'),decode('windows-1252','Öl'),decode('windows-1252','ßig'),'Renee',decode('windows-1252','ärgerlich'))));
QuoteRenee + Renée + Vertrag + ßig + Ärger + ärgerlich + Öl + Übel
Encode und
locale:1 2
use locale; print encode('iso-8859-15',join(' + ',sort {lc $a cmp lc $b} ('Vertrag',decode('windows-1252','Übel'),decode('windows-1252','Ärger'),decode('windows-1252','Renée'),decode('windows-1252','Öl'),decode('windows-1252','ßig'),'Renee',decode('windows-1252','ärgerlich'))));
QuoteRenee + Renée + Vertrag + ßig + Ärger + ärgerlich + Öl + Übel
POSIX und den Werten de_DE.ISO8859-1, de_DE.iso88591 oder de_DE:1 2 3 4
use POSIX qw(locale_h); use locale; setlocale(LC_CTYPE, "de_DE"); print join(' + ',sort {lc $a cmp lc $b} ('Vertrag','Übel','Ärger','Renée','Öl','ßig','Renee','ärgerlich'));
QuoteRenee + Renée + Vertrag + ßig + Ärger + ärgerlich + Öl + Übel
POSIX und den Werten de, german oder german.iso88591:1 2 3 4
use POSIX qw(locale_h); use locale; setlocale(LC_CTYPE, "de"); print join(' + ',sort {lc $a cmp lc $b} ('Vertrag','Übel','Ärger','Renée','Öl','ßig','Renee','ärgerlich'));
QuoteRenee + Renée + Vertrag + Ärger + Öl + Übel + ßig + ärgerlich
locale:1 2
use locale; print join(' + ',sort {lc $a cmp lc $b} ('Vertrag','Übel','Ärger','Renée','Öl','ßig','Renee','ärgerlich'));
QuoteRenee + Renée + Vertrag + Ärger + Öl + Übel + ßig + ärgerlich
$uniccol->cmp($a->[$z],$b->[$z]);
2015-01-02T11:42:00 GUIfreundVersuche doch mal, den Sort durch eine Serie von Sorts über die einzelnen Spalten zu ersetzen, beginnend mit der letzten Spalte
2015-01-02T11:42:00 GUIfreundSchwarzsche Transformation einsetzen
2015-01-02T17:17:12 bianca2015-01-02T11:42:00 GUIfreundVersuche doch mal, den Sort durch eine Serie von Sorts über die einzelnen Spalten zu ersetzen, beginnend mit der letzten Spalte
Das verstehe ich nicht. Was genau meinst du damit?
2015-01-02T17:17:12 biancaAm Ende hab ich jetzt eine Lösung ..... Reicht für meinen Bedarf.
2015-01-04T14:15:53 GUIfreundDein komplexer Vergleichskode hat sich dabei auf einen Einzeiler reduziert.
2015-01-05T07:53:56 bianca2015-01-04T14:15:53 GUIfreundDein komplexer Vergleichskode hat sich dabei auf einen Einzeiler reduziert.
Bitte zeig mir den Einzeler mal kurz. Ich weiß nicht, wie das aussähe, bin sonst mit einem einfachen sort a/b immer hingekommen. Würde hier gern was Neues lernen.
2015-01-05T18:06:44 biancaHmm, aber was ist denn das Neue an Deinem Vorschlag?
2015-01-04T14:15:53 GUIfreundDas dürfte unter'm Strich einen deutlichen Geschwindigkeitsgewinn bringen.
2015-01-05T18:06:44 biancaIch hab ein mehrspaltiges Hash und in zwei Arrays hab ich einmal die Art (nummerisch oder alpha) und im anderen die Reihenfolge (1 = aufwärts und 0 = abwärts) für jede einzelne Spalte.
Wie setze ich denn damit deinen Vorschlag um?
2015-01-06T12:52:20 GUIfreundJede Spalte hat ja ihren eigenen Sort. Für numerische Spalten nimmst du den numerischen Vergleichsoperator <=>, und für abwärts vertauschst du $a und $b (gleich beim Kodieren - bitte kein if). Alles wie gehabt.
2015-01-06T12:52:20 GUIfreundÜbrigens kann es durchaus passieren, dass sich der Geschwindigkeitsgewinn am Ende als gar nicht so berauschend herausstellt. Schließlich benutzt du nach wie vor die Methode $uniccol->cmp. Da könntest du nur auf den Ehrgeiz des Autors hoffen, daran noch zu feilen.
1 2 3 4 5 6 7 8 9 10 11 12
if ($methode == 1) { my $start = time(); my $uniccol = Unicode::Collate->new(); foreach my $z (reverse (0 .. $spalten-1)) { @{$data{spalten}} = sort {$uniccol->cmp($a->[$z],$b->[$z])} @{$data{spalten}}; } # foreach my $feldref (@{$data{spalten}}) { # print "@$feldref\n"; # } print "\nLaufzeit: ".(time()-$start); }
1 2 3 4
use Unicode::Collate; my $alphasorter_modul = Unicode::Collate->new(); my $alphasorter_regex = qr{[^0-9 a-z!"§$%&/()=?\{\[\]\}\]><|_\-+*,.:;#'~\^]}ix; my $sort = sub { $_[0] =~ $alphasorter_regex || $_[1] =~ $alphasorter_regex ? $alphasorter_modul->cmp($_[0],$_[1]) : lc $_[0] cmp lc $_[1] };
Quote$Collator->getSortKey($a) cmp $Collator->getSortKey($b)
is equivalent to
$Collator->cmp($a, $b)
1 2 3 4 5
my @sorted = map { $_->[0] } sort { $a->[1] cmp $b->[1] } map { [ $_, $Collator->getSortKey($_) ] } @zuSortieren;
2015-01-08T08:47:30 RaubtierMan sollte vielleicht nicht von allen Spalten den Key berechnen, wenn man z.B. nie die 2. Spalte vergleicht, wenn z.B. alle 1. Spalten unterschiedlich sind.
1 2 3 4 5 6
use Time::HiRes qw( gettimeofday tv_interval ); my $t0 = [ gettimeofday ]; # your code here print "Time elapsed: " . (tv_interval( $t0 )) . " seconds\n";
Wie installiert man ein Modul?