Sortieren von Listen mit sort()

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
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.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
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)
mitsuhiko
User
Beiträge: 1790
Registriert: Donnerstag 28. Oktober 2004, 16:33
Wohnort: Graz, Steiermark - Österreich
Kontaktdaten:

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.
TUFKAB – the user formerly known as blackbird
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";
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.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

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.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
jens
Python-Forum Veteran
Beiträge: 8502
Registriert: Dienstag 10. August 2004, 09:40
Wohnort: duisburg
Kontaktdaten:

Leonidas hat geschrieben:Keine globals, keine unbenötigten Variablen.
Und was ist mit zk ??? :lol:

GitHub | Open HUB | Xing | Linked in
Bitcoins to: 1JEgSQepxGjdprNedC9tXQWLpS424AL8cd
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

jens hat geschrieben:Und was ist mit zk ??? :lol:
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).
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
BlackJack

Leonidas hat geschrieben:
jens hat geschrieben:Und was ist mit zk ??? :lol:
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. :wink:
Antworten