sort von Strings und Zahlen

sort von Strings und Zahlen

am 06.01.2007 09:07:19 von Phil

Hallo,

ich möchte ein Array mit Strings und Zahlen sortieren. Der cmp Operator
interpretiert die Zahlen dann natürlich auch als Strings und sortiert sie
nicht richtig:

1
a
b
2
3
10
100

sort {$a cmp $b}:

1
10
100
2
3
a
b

Ich hätte das Array gerne so, dass am Anfang die Zahlen in ihrer
numerisch richtigen Reihenfolge und danach die Strings auch
richtig sortiert kommen.

Das klingt für mich nach einer FAQ, aber habe irgendwie nichts
gefunden...
Wie macht man das am besten (soll heissen: am performantesten)?


Grüße, Phil

Re: sort von Strings und Zahlen

am 06.01.2007 09:20:44 von Bjoern Hoehrmann

* Philipp E. Letschert wrote in de.comp.lang.perl.misc:
>Ich hätte das Array gerne so, dass am Anfang die Zahlen in ihrer
>numerisch richtigen Reihenfolge und danach die Strings auch
>richtig sortiert kommen.

Dann musst du <=> für alle Zahlenpaare benutzen, und cmp für den Rest,
also `($a =~ /^\d+$/ and $b =~ /^\d+$/) ? $a <=> $b : $a cmp $b;` oder
wie auch immer du eine Zahl jetzt definierst. Alternativ kannst du
auch nur <=> benutzen und hinterher das Array an der Zahlen/String
Grenze splitten, und deren Reihenfolge ändern.
--
Björn Höhrmann · mailto:bjoern@hoehrmann.de · http://bjoern.hoehrmann.de
Weinh. Str. 22 · Telefon: +49(0)621/4309674 · http://www.bjoernsworld.de
68309 Mannheim · PGP Pub. KeyID: 0xA4357E78 · http://www.websitedev.de/

Re: sort von Strings und Zahlen

am 06.01.2007 10:17:23 von Phil

Am Sat, 06 Jan 2007 09:20:44 +0100 schrieb Bjoern Hoehrmann:

> * Philipp E. Letschert wrote in de.comp.lang.perl.misc:
>>Ich hätte das Array gerne so, dass am Anfang die Zahlen in ihrer
>>numerisch richtigen Reihenfolge und danach die Strings auch
>>richtig sortiert kommen.
>
> Dann musst du <=> für alle Zahlenpaare benutzen, und cmp für den Rest,
> also `($a =~ /^\d+$/ and $b =~ /^\d+$/) ? $a <=> $b : $a cmp $b;`

Merci!

Re: sort von Strings und Zahlen

am 06.01.2007 13:15:29 von Thomas Wittek

Bjoern Hoehrmann schrieb:
> `($a =~ /^\d+$/ and $b =~ /^\d+$/) ? $a <=> $b : $a cmp $b;`

Performant ist das vermutlich nicht.
Einfacher kann man so auf eine Zahl prüfen:

`($a eq $a+0 and $b eq $b+0) ? $a <=> $b : $a cmp $b;`

--
Thomas Wittek
http://gedankenkonstrukt.de/
Jabber: streawkceur@jabber.i-pobox.net

Re: sort von Strings und Zahlen

am 06.01.2007 13:26:27 von Frank Seitz

Thomas Wittek wrote:
> Bjoern Hoehrmann schrieb:
>>
>>`($a =~ /^\d+$/ and $b =~ /^\d+$/) ? $a <=> $b : $a cmp $b;`
>
> Performant ist das vermutlich nicht.

Da sehe ich weniger das Problem, eher darin, dass
es ein recht kruder Zahl-Test ist.

> Einfacher kann man so auf eine Zahl prüfen:
>
> `($a eq $a+0 and $b eq $b+0) ? $a <=> $b : $a cmp $b;`

Für jemanden, der sauber arbeitet, sprich mit -w oder
"use warnings", ist das eher nicht zu empfehlen.

Grüße
Frank
--
Dipl.-Inform. Frank Seitz; http://www.fseitz.de/
Anwendungen für Ihr Internet und Intranet
Tel: 04103/180301; Fax: -02; Industriestr. 31, 22880 Wedel

Re: sort von Strings und Zahlen

am 06.01.2007 14:10:51 von Joergen Lang

Philipp E. Letschert schrieb:
> Hallo,
>
> ich möchte ein Array mit Strings und Zahlen sortieren. Der cmp Operator
> interpretiert die Zahlen dann natürlich auch als Strings und sortiert sie
> nicht richtig:

[...]

> Ich hätte das Array gerne so, dass am Anfang die Zahlen in ihrer
> numerisch richtigen Reihenfolge und danach die Strings auch
> richtig sortiert kommen.
>
> Das klingt für mich nach einer FAQ, aber habe irgendwie nichts
> gefunden...

Genua!

$> perldoc -q sort

bzw.

http://tinyurl.com/yyr878
(Da die direkte Adresse noch kryptischer ist, hier als "tiny".)

Gruss,

Joergen

Re: sort von Strings und Zahlen

am 06.01.2007 15:22:49 von Slaven Rezic

"Philipp E. Letschert" writes:

> Hallo,
>
> ich möchte ein Array mit Strings und Zahlen sortieren. Der cmp Operator
> interpretiert die Zahlen dann natürlich auch als Strings und sortiert sie
> nicht richtig:
>
> 1
> a
> b
> 2
> 3
> 10
> 100
>
> sort {$a cmp $b}:
>
> 1
> 10
> 100
> 2
> 3
> a
> b
>
> Ich hätte das Array gerne so, dass am Anfang die Zahlen in ihrer
> numerisch richtigen Reihenfolge und danach die Strings auch
> richtig sortiert kommen.
>
> Das klingt für mich nach einer FAQ, aber habe irgendwie nichts
> gefunden...
> Wie macht man das am besten (soll heissen: am performantesten)?

Versuch's mal mit Sort::Naturally.

--
Slaven Rezic - slaven rezic de

tkrevdiff - graphical display of diffs between revisions (RCS, CVS or SVN)
http://ptktools.sourceforge.net/#tkrevdiff

Re: sort von Strings und Zahlen

am 06.01.2007 19:53:29 von Phil

Am Sat, 06 Jan 2007 15:22:49 +0100 schrieb Slaven Rezic:

> "Philipp E. Letschert" writes:
>>
>> Wie macht man das am besten (soll heissen: am performantesten)?
>
> Versuch's mal mit Sort::Naturally.

Danke für die Antworten, habe mal die Möglichkeiten probiert und
gebankwertet:

Sort::Naturally ist von der Performance nicht zu empfehlen, die zuerst
genannte Methode ist tatsächlich am schnellsten:

use Scalar::Util qw(looks_like_number);
sort {
(looks_like_number($a) and looks_like_number($b))
? $a <=> $b
: $a cmp $b;
}

Caching der Werte von looks_like_number() mittels 'Orcish Manoeuvre' [*]
kann dann noch einen kleinen Performance-Kick bringen, aber nur wenn
man vorher weiß, dass viele lange Strings im Array vorkommen und ein
hoher Prozentsatz der vergleichenden Werte mehrfach auftaucht (~ >50%).
Sonst ist das nur zusätzlicher Overhead, weil looks_like_number ist
schnell genug...


Grüße, Phil


[*] gleiche Schublade wie Schwartz'sche Transformation

Re: sort von Strings und Zahlen

am 08.01.2007 18:13:34 von Ingo Menger

Philipp E. Letschert schrieb:

> Am Sat, 06 Jan 2007 15:22:49 +0100 schrieb Slaven Rezic:
>
> > "Philipp E. Letschert" writes:
> >>
> >> Wie macht man das am besten (soll heissen: am performantesten)?
> >
> > Versuch's mal mit Sort::Naturally.
>
> Danke für die Antworten, habe mal die Möglichkeiten probiert und
> gebankwertet:
>
> Sort::Naturally ist von der Performance nicht zu empfehlen, die zuerst
> genannte Methode ist tatsächlich am schnellsten:
>
> use Scalar::Util qw(looks_like_number);
> sort {
> (looks_like_number($a) and looks_like_number($b))
> ? $a <=3D> $b
> : $a cmp $b;
> }
>
> Caching der Werte von looks_like_number() mittels 'Orcish Manoeuvre' [*]
> kann dann noch einen kleinen Performance-Kick bringen, aber nur wenn
> man vorher weiß, dass viele lange Strings im Array vorkommen und ein
> hoher Prozentsatz der vergleichenden Werte mehrfach auftaucht (~ >50%).
> Sonst ist das nur zusätzlicher Overhead, weil looks_like_number ist
> schnell genug...

Noch schneller dürfte es gehen, wenn Du einmal durch die Liste gehst
und dabei zwei neue Listen erzeugts, eine mit Zahlen, eine mit Strings,
dann die beiden Listen separat sortierst und in der von Dir
gewünschten Reihenfolge wieder aneinanderhängst.
Begründung: looks_like_number wird dann für jedes Element genau
einmal aufgerufen, beim Sortieren kann das durchaus mehrfach passieren,
abgesehen von der sonstigen Logik. Motto: soviel wie möglich Arbeit
aus dem Hotspot (also der Vergleichsfunktion) rausnehmen.

Re: sort von Strings und Zahlen

am 09.01.2007 13:05:00 von Ferry Bolhar

Ingo Menger:

> Noch schneller dürfte es gehen, wenn Du einmal durch die Liste gehst
> und dabei zwei neue Listen erzeugts, eine mit Zahlen, eine mit Strings,
> dann die beiden Listen separat sortierst und in der von Dir
> gewünschten Reihenfolge wieder aneinanderhängst.
> Begründung: looks_like_number wird dann für jedes Element genau
> einmal aufgerufen, beim Sortieren kann das durchaus mehrfach passieren,
> abgesehen von der sonstigen Logik. Motto: soviel wie möglich Arbeit
> aus dem Hotspot (also der Vergleichsfunktion) rausnehmen.

Stichwort: Schwartz'sche Transformation:

http://perl-seiten.homepage.t-online.de/html/perl_schw.html

LG, Ferry

--
Ing Ferry Bolhar
Magistrat der Stadt Wien - MA 14
A-1010 Wien
E-Mail: bol@adv.magwien.gv.at