Seite 1 von 1
Sortieren von Listen mit sort()
Verfasst: Mittwoch 14. September 2005, 15:31
von Charly
Hallo,
ich will ein Perl-Code in Python umsetzten. Dabei komme ich an eine Stelle, an der ich nicht weiter komme.
Perl-Code
Code: Alles auswählen
sub sort_by_ref {
return substr($zk, $refs[$a]) cmp substr($zk, $refs[$b]);
}
# @refs ist einfach ein Feld von 0-5
@sort_refs = sort sort_by_ref @refs;
In Perl funktioniert das wunderbar. Allerdings kappt das in Python so nicht!
Code: Alles auswählen
def sort_by_ref():
global zk
global refs
return cmp(zk[:refs[a]], zk[:refs[b]])
sort_refs = refs.sort(sort_by_ref())
Fehlermeldung: NameError: global name 'a' is not defined
Für 'b' wird das gleiche gelten!
Hat einer eine Idee wie das bei Python geht? Ich müsste auf die Listen-Werte von der Sort-Funktion zugreifen können, wenn ich den Perl-Code richtig interpretiert habe!
Edit (Leonidas): Code in Python-Tags gesetzt.
Verfasst: Mittwoch 14. September 2005, 15:42
von Leonidas
Was macht denn diese Perl-Funktion genau?
Funktionen 1:1 in Python zu schreiben wird scheitern, schon allein die Vorraussetzung global zu benutzen ist schon recht unangenehm.
Verfasst: Mittwoch 14. September 2005, 15:48
von Charly
Die Funktion gehört zu einem Programm, das die längste doppelt vorkommende Zeichenkette in einem Text sucht.
Die Funktion sortiert das Referenzarray refs
Bsp.
Banana
längste doppelte Zeichenkette "ana"
zk = banana
refs = [0,1,2,3,4,5]
sort_refs soll werden [5,3,1,0,4,2] das entspricht aaabnn (Sortiert Banana)
Verfasst: Mittwoch 14. September 2005, 15:52
von mitsuhiko
Dann poste mal die Ganze Perl Funktion, und deinen Python Code. Sonst ist das hier nur Raten.
Python findet a nicht, wie soll es auch, immerhin wurde es ja nicht initialisiert.
Verfasst: Mittwoch 14. September 2005, 15:58
von Gast
In Perl ist a und b auch nicht initialisiert!
a und b sind die Werte mit dem die sort Funktion in Perl arbeitet!
Auch wenn ich glaube das der Code in diesem Falle nicht weiterhilft, hier der Perl-Code
Code: Alles auswählen
use strict;
use Data::Dumper;
use English;
#-------------------------------------------------------------------
# Variablendeklaration
#-------------------------------------------------------------------
my $zk = ""; # Gesamte Zeichenkette
my @refs; # Referenz_Array
my @sort_refs; # Sortiertes Referenz_Array
my $temp; # Temp
my $maxIndex = 0; # Start Index zur Maximalen Länge
my $maxLen = 0; # Maximale Länge
#-------------------------------------------------------------------
# Funktion zum lexikalischen Sortieren von Referenzarrays
# Die Funktion verlgeicht bzw. sortiert 2 Substrings
# return <0 / 0 / >0
#-------------------------------------------------------------------
sub sort_by_ref {
return substr($zk, $refs[$a]) cmp substr($zk, $refs[$b]);
}
#-------------------------------------------------------------------
# Gibt die Laenge der gleichen Anfangszeichenketten zurueck
# Vergleicht 2 Zeichenketten
# param: 2 strings
# return: Anzahl der länge der gleichen Zeichen
#-------------------------------------------------------------------
sub common_substring {
my $substring1 = shift;
my $substring2 = shift;
my $min;
my $count = 0;
if(length $substring1 < length $substring2){
$min = length $substring1;
}
else{
$min = length $substring2;
}
# Durläuft so lange wie die länge des kürzeren Substrings
# Zählt die anzahl der gleichen Zeichen
for (my $i = 0; $i < $min; $i++){
if (substr($substring1, $i, 1) ne substr($substring2, $i, 1)) {
last;
}
$count++;
}
return $count;
}
#-------------------------------------------------------------------
# Einlesen der Quelldatei und Ersetzen von Zeilenumbruechen
# durch Leerzeichen
#-------------------------------------------------------------------
undef $INPUT_RECORD_SEPARATOR;
open(INPUT, "/home/Charly/Skriptsprachen-Dateien/Stechlin-01.txt") || die "Datei nicht gefunden\n";
$zk = <INPUT>;
close(INPUT);
$zk =~ s/\n/ /g;
#-------------------------------------------------------------------
# Anlegen des Referenzarrays
# Feld[i] = i
#-------------------------------------------------------------------
for(my $i = 0; $i < length $zk; $i++){
$refs[$#refs +1] = $i;
}
#-------------------------------------------------------------------
# Sortieren des Referenzarrays
# Alphabetisch
#-------------------------------------------------------------------
@sort_refs = sort sort_by_ref @refs;
#-------------------------------------------------------------------
# Suchen nach doppelt vorkommenden Zeichenketten
#-------------------------------------------------------------------
for(my $i = 0; $i <= $#sort_refs; $i++){
$temp = substr $zk, $sort_refs[$i];
# Wenn die von common_substring zrückgegebene länge größer ist als maxLen,
if(common_substring($temp, (substr $zk, $sort_refs[$i+1])) > $maxLen){
$maxLen = common_substring($temp, substr $zk, $sort_refs[$i+1]);
$maxIndex = $sort_refs[$i];
#print $maxIndex." ".$maxLen."\n";
}
}
print $#sort_refs."\n";
print "Laengste doppelt vorkommende Zeichenkette: \n\n";
print substr $zk, $maxIndex, $maxLen; # Ausgabe der längsten Zeichenkette (Zeichenkette, Start, Länge)
print "\n$maxLen";
Verfasst: Mittwoch 14. September 2005, 16:38
von Charly
Die Lösung habe ich jetzt mit Hilfe von google.de erraten:
Code: Alles auswählen
#-------------------------------------------------------------------
# Funktion zum lexikalischen Sortieren von Referenzarrays
#-------------------------------------------------------------------
def sort_by_ref(a,b):
global zk
global refs
start = zk[b:b+1]
ende = zk[a:a+1]
erg = cmp(start, ende)
return erg
#-------------------------------------------------------------------
# Sortieren des Referenzarrays
#-------------------------------------------------------------------
refs_sort = refs[:]
refs_sort.sort(sort_by_ref)
Edit (Leonidas): Code in Python-Tags gesetzt.
Verfasst: Mittwoch 14. September 2005, 17:28
von Leonidas
Das finde ich besser:
Code: Alles auswählen
def sort_by_ref(a,b):
start = zk[b:b+1]
ende = zk[a:a+1]
return cmp(start, ende)
Keine globals, keine unbenötigten Variablen.
Verfasst: Mittwoch 14. September 2005, 17:57
von jens
Leonidas hat geschrieben:Keine globals, keine unbenötigten Variablen.
Und was ist mit zk ???

Verfasst: Mittwoch 14. September 2005, 18:04
von Leonidas
jens hat geschrieben:Und was ist mit zk ???

zk ist die Liste, die wird aber nicht mit dem Schlüsselwort unnötigerweise als global definiert.
Man kann natürlich auch OOP anwenden, aber zumindest sollte man vermeiden auf globale Variablen schreibend zuzugreifen (Nebeneffekt/wirkung).
Verfasst: Mittwoch 14. September 2005, 22:11
von BlackJack
Leonidas hat geschrieben:jens hat geschrieben:Und was ist mit zk ???

zk ist die Liste, die wird aber nicht mit dem Schlüsselwort unnötigerweise als global definiert.
Man kann natürlich auch OOP anwenden, aber zumindest sollte man vermeiden auf globale Variablen schreibend zuzugreifen (Nebeneffekt/wirkung).
Wobei ich hier mal wieder anmerken möchte das es in Python keine Variablen im klassischen Sinn gibt. Nebeneffekte kann man ohne ``global`` problemlos haben wenn die Objekte "mutable" sind, man kann nur den Namen eines "äusseren" Objekts nicht an ein anderes Objekt binden wenn man es nicht als ``global`` deklariert.
Und auch ich bin der Meinung der anderen: Man sollte keine Programme zwischen verschiedenen Programmiersprachen 1:1 umsetzen sondern lieber das Problem verstehen und in der Zielsprache formulieren.
Ich denke man muss auch noch nichtmal OO anwenden um auf die globalen Namen zu verzichten. Konsequent Funktionsparameter und Rückgabewerte benutzen reicht für den Anfang.
Diese nette kleine Funktion erstellt zum Beispiel ohne ``global`` eine sortierte Referenzliste für die übergebene Zeichenkette:
Code: Alles auswählen
from itertools import count
from operator import itemgetter
def sorted_refs(string):
return map(itemgetter(1), sorted(zip(string, count())))
Schön kurz, oder? Und fast so komisch wie Perl-Code, dafür aber ohne komische Zeichen.
