Thread Unicode::Collate -> sehr langsam? (26 answers)
Opened by bianca at 2014-12-27 18:42

bianca
 2014-12-27 18:42
#178920 #178920
User since
2009-09-13
7016 Artikel
BenutzerIn

user image
Hallo!
Auf der Suche nach einer Lösung für die richtige Sortierung mit Umlauten unter Nutzung von ANSI (latin1/latin15) Zeichencode stieß ich auf Hash mit Umlauten sortieren und freute mich. Endlich sind die Umlaute korrekt sortiert. Vorhin habe ich aber festgestellt, dass diese Lösung leider viel zu langsam ist.

Zum Nachvollziehen:
Code (perl): (dl )
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);
}

Das mit den Spalten ist deshalb drin, weil das mir auch so läuft. Denn ich habe häufig die Situation, dass mehrere Spalten selbe Inhalte haben, daher soll er von links nach rechts alphabetisch durchsortieren.

Methode mit CPAN:Unicode::Collate läuft bei diesen Mengen auf meinem Rechner 14 Sekunden und mit lc weniger als eine volle Sekunde. Wobei CPAN:Unicode::Collate natürlich korrekt sortiert und lc nicht.
Kann ich eine korrekte Sortierung auch schneller erreichen? Kann man was optimieren?
Muss ich vielleicht an der Behandlung der Spalten etwas ändern, um schneller zu werden?

Der obere Code dient übrigens nur der Geschwindigkeitsmessung, nicht der Darstellung der korrekten Sortierung von Umlauten!
Das Thema Umlaute kann man hiermit testen (ACHTUNG, ANSI, kein UTF8!)
Code (perl): (dl )
1
2
3
my $uniccol = Unicode::Collate->new();
my @s = sort { $uniccol->cmp($a,$b) } ('Vertrag','Übel','Ärger','Öl','ßig','ärgerlich');
print join(' + ',@s);
10 print "Hallo"
20 goto 10

View full thread Unicode::Collate -> sehr langsam?