Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Natürliche Sortierung implementieren ("img2.jpg" vor "img10.jpg")

Moderationshinweis von herbivore (21.12.2010 - 11:48:49):

Abgeteilt von ListView Sortierung (gehört eigentlich zu Sortierung der ListView Items).


Dieser Thread führt beim Durchlesen sehr plastisch vor Augen, viel Aufwand es bedeutet, einen (damaligen) Anfänger selbst bei einer typischen, relativ einfachen Übungsaufgabe bis zu einer fertigen Lösung an die Hand zu nehmen. Sicher kann man das mal ausnahmsweise und exemplarisch machen und ein solche individuelle Tutoriumssitzung kann für den einzelnen Anfänger ein großer Gewinn sein, aber es ist klar zu erkennen, dass dies im Allgemeinen die Zeit und die Hilfsbereitschaft der Helfer deutlich überstrapaziert.

Vielleicht wird dadurch wieder ein bisschen klarer, warum wir von Anfängern - getreu dem Motto "gemeinsam mehr erreichen" - mittlerweile erwarten, dass sie ihren Teil, nämlich das eigenständige Erarbeiten der Grundlagen, selbst übernehmen, bevor sie Fragen im Forum stellen.


Der Algorithmus von natcomapre ist in diesem Beitrag weiter unten beschrieben.
Ein fertiges Code-Snippet, welches Interger-Zahlen inkl. führender Nullen berücksichtigt, in diesem Beitrag weiter unten.

Ein weiteres Snippet findet sich in Natürliche Sortierung (Natural Sorting) für C#.

herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

Themenstarter:

Natürliche Sortierung implementieren ("img2.jpg" vor "img10.jpg")

beantworten | zitieren | melden

Hallo -acid-,

naja, so schwer sollte natsort ja nicht zu implementieren sein. Wenn ich das richtig sehe, geht es ja hauptsächlich darum, dass "10.jpg" hinter "2.jpg" einsortiert wird.

herbivore
private Nachricht | Beiträge des Benutzers
-acid-
myCSharp.de - Member



Dabei seit:
Beiträge: 891
Herkunft: Hessen

beantworten | zitieren | melden

tzja sollte... ich habe aber nicht wirklich ahnung wíe ich das umsetzen sollte.
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Hallo -acid-,

das entscheidende der Sortierung ist ja nur der eigentliche Vergleich, nennen wir ihn natcmp, der zwei Strings bekommt. natcmp tut folgendes: Die beiden Strings von vorne zeichenweise zu vergleichen, solange das Zeichen keine Ziffer ist. Wenn das Zeichen eine Ziffer ist, zählt man die Länge der hier beginnenden Zahlen. Ist sind diese Längen gleich setzt man den zeichenweisen Vergleich für alle folgenden Ziffern fort, als wären sie Nicht-Ziffer-Zeichen.

Solange alle Zeichen und Zahlenlängen gleich sind, geht es immer zum nächsten Zeichen. Wenn irgendwann ein Unterschied festgestellt wird, liefert man -1, wenn das Zeichen im ersten String bzw. die Zahlenlänge des ersten Strings kleiner ist, +1 wenn es/sie größer ist. Kommt man zum Ende eines Strings, ohne einen Unterschied festgestellt zu haben, liefert man -1, wenn der erste String kürzer ist, +1 wenn der zweite kürzer ist und 0, wenn beide Strings gleichlang sind.

Das ganze berücksichtigt noch keine führenden Nullen. Das lässt sich dann aber auch später ergänzen. Außerdem geht dieser Algorithmus davon aus, dass alle auftretenden Zahlen als Integer betrachtet werden sollen. Eine Erweiterung auf gebrochene Zahlen wäre denkbar.

HTH

herbivore
private Nachricht | Beiträge des Benutzers
-acid-
myCSharp.de - Member



Dabei seit:
Beiträge: 891
Herkunft: Hessen

beantworten | zitieren | melden

Also ich hab das mal so gemacht:

public int Compare(object x, object y)
{
string s1 = ((ListViewItem)x).SubItems[col].Text;
string s2 = ((ListViewItem)y).SubItems[col].Text;
int output = String.Compare(s1, s2);
return output;
}

Ok habe jetzt versucht dir zu folgen und das bisher von der Logik her so verstanden, als wäre result 1 größer und result -1 kleiner. Ich soll also jetzt solange vergleichen bis das Zeichen keine Ziffer ist.

Hm. Ich komme war nicht so ganz hinterher mit deiner Verfahrensweise, aber ich versuche mal das irgendwie hinzubiegen.
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Hallo -acid-,

was ich meine ist, dass du 'String.Compare(s1, s2)' durch 'MyClass.NatCompare (s1, s2)' ersetzen soltest. Die Beschreibung von oben wäre dann die Implementierung von MyClass.NatCompare (s1, s2).

Um es nochmal mit anderen Worten etwas kürzer zu sagen: Einen String kann man vergleichen, indem man seine Zeichen von links nach rechts einzeln vergleicht. Bei NatSort sollen aber eingebettete Zahlen nicht ziffernweise verglichen werden, sondern nach ihrem Wert. Der Wert einer Zahl ist immer größer, wenn sie länger ist als die andere Zahl (von führende Nullen abgesehen). Deshalb wird statt dem Wert der Zahlen erstmal deren Länge verglichen. Erst wenn die Zahlen gleichlang sind, wird ziffernweise verglichen, denn hier bringt der ziffernweise Vergleich dasselbe Ergebnis wie ein Vergleich nach Wert (von den führenden Nullen, wie schon gesagt, abgesehen).

Anders ausgedrückt vergleicht NatSort zeichenweise, betrachtet aber eingebettete Zahlen als *ein* Zeichen.

herbivore
private Nachricht | Beiträge des Benutzers
-acid-
myCSharp.de - Member



Dabei seit:
Beiträge: 891
Herkunft: Hessen

beantworten | zitieren | melden

ok dein prinzip leuchtet mir ein, aber ich glaube nicht, dass ich das technisch umsetzen kann. gibt es nicht irgendwo eine umsetzung?
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Hallo -acid-,

meiner Einschätzung wäre die Umsetzung, zumal nach der schon sehr detailierten Beschrieibung, eine typische Übungsaufgabe, wie sie in Büchern für Einsteiger vorkommen - keinesfalls viel schwerer. Das solltest du eigenlich hinbekommen!

herbivore
private Nachricht | Beiträge des Benutzers
-acid-
myCSharp.de - Member



Dabei seit:
Beiträge: 891
Herkunft: Hessen

beantworten | zitieren | melden

Klar sollte ich. Nur ist das Problem einfach, dass ich nicht direkt verstehe, wie ich das umsetzen soll. Wie gesagt ich versuche es...
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Hallo -acid-,

schreib erstmal einen eigenen normalen zeichenweisen Vergleich MyClass.Compare (s1, s2).

Von vorne zeichenweise vergleichen. Wenn Zeichen unterschliedlich -1 bzw. +1 liefern, sonst zum nächsten Zeichen. Kommt man zum Ende eines Strings, ohne einen Unterschied festgestellt zu haben, liefert man -1, wenn der erste String kürzer ist, +1 wenn der zweite kürzer ist und 0, wenn beide Strings gleichlang sind.

Mit dieser Basis solle eine Erweiterung auf NatCompare um einiges leicher sein.

herbivore
private Nachricht | Beiträge des Benutzers
-acid-
myCSharp.de - Member



Dabei seit:
Beiträge: 891
Herkunft: Hessen

beantworten | zitieren | melden

bin dabei...
private Nachricht | Beiträge des Benutzers
-acid-
myCSharp.de - Member



Dabei seit:
Beiträge: 891
Herkunft: Hessen

beantworten | zitieren | melden

frage:

wie lasse ich denn am besten meine schleife durlaufen?

gut ich könnte jetzt den größten wert beider strings testen und dann die schleife entsprechend oft durchlaufen lassen, aber geht das nicht auch ähnlich wie ich das hier habe?

for (int i=0; i<s1.Length && s2.Lenght; i++)
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Hallo -acid-,

mit


for (int i=0; i < s1.Length && i < s2.Lenght; i++)
würde es gehen, ich denke es ist aber praktischer nur 'i < s1.Length' als Schleifenbedingung zu nehmen und i ≥ s2.Lenght als erstes in der Schleife zu fragen.

herbivore
private Nachricht | Beiträge des Benutzers
-acid-
myCSharp.de - Member



Dabei seit:
Beiträge: 891
Herkunft: Hessen

beantworten | zitieren | melden

public int NatCompare(string s1, string s2)
		{
			for (int i=0; i<s1.Length; i++)
			{
				string letter_s1 = s1.Substring(i, 1);
				string letter_s2 = s2.Substring(i, 1);
				
				if (s1.Length == s2.Length)
				{
					return 0;
				}
				else
				{
					if (i ≥ s2.Length)
					{
						return 1;
					}
					else
					{
						if (letter_s1 != letter_s2)
						{
							return -1;
						}
					}
				}				
			}
			
			return -1;
		}

So ist jetzt so wie ich das verstanden habe...
- Sind aber noch Fehler drin, weil er nicht richtig sortiert.

(Warum darf ich meine eigenen Beiträge nicht löschen, war ausversehen nen Doppelpost.)
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Hallo -acid-,

vermutlich wirst du beim Testen feststellen, dass es nicht funktioniert. :-)

Statt "sX.Substring(i, 1)" solltest du besser 'sX ' benutzen und kannst dann auch auf letter_sX verzichten.

Die Längen von s1 und s2 (innerhalb der Schleife zu testen) ist - sorry - Quatsch. Was immer nur interessiert ist ein Vergleich von i mit der jeweiligen Länge.

Und bei dem Vergleich von letter_s1 und letter_s2 (also besser - wie oben gesagt - s1 und s2 ) kommt es ja gerade darauf an, *welches* Zeichen größer bzw. kleiner ist. Entsprechend +1 oder -1 liefern.

Ansonsten geht das schon mal in die richtige Richtung!

HTH

herbivore
private Nachricht | Beiträge des Benutzers
-acid-
myCSharp.de - Member



Dabei seit:
Beiträge: 891
Herkunft: Hessen

beantworten | zitieren | melden

richtig das hab ich festgestellt.

ach ok wusste ich nicht das es so auch geht *g*

aber du hast doch gesagt ich sollte die länge vergleichen...
hm jetzt wo ich deine beiträge das 20. mal lese, verstehe ich etwas mehr. das heisst also wenn zahlen drin vorkommen, dass es trotzdem als ein zeichen betrachtet werden soll.
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Hallo -acid-,
Zitat
"sX.Substring(i, 1)" lasse i´ch mir immer ein zeichen ausgeben um es zu vergleichen
Das ist mit klar! Ich meine eben nur, dass es besser ist stattdessen 'sX ' zu benutzen. Mit sX.Substring(i, 1) bekommst du einen String, der das eine Zeichen enthält, mit sX bekommst du direkt das Zeichen (als char).
Zitat
du warst es auch, der sagte ich sollte die länge der strings vergleichen.
Was die Längen angeht habe ich geschrieben "Kommt man zum Ende eines Strings ...". Bei deinem Vergleich wird aber sofort beim ersten (und jedem weiteren) Schleifendurchlauf gerprüft, ob die Strings gleich lang sind. Da in diesem Fall 0 zurückgegeben wird, bedeutet das, dass Strings als gleich betrachtet werden, wenn sie gleich lang sind - unabhängig von Inhalt. Das will man offensichtlich nicht.

Aber es wird schon klappen!

herbivore
private Nachricht | Beiträge des Benutzers
-acid-
myCSharp.de - Member



Dabei seit:
Beiträge: 891
Herkunft: Hessen

beantworten | zitieren | melden

herbivore: so ich habe mal ne nacht drüber geschlafen und ich denke ich blicke heute mehr durch. ich glaube mein problem war, dass ich zu viele dateien hatte und zuschnell vorrangegangen bin. jetzt gehe ich mal step by step durch.

also erstmal habe ich "1.jpg" und "10.jpg" welches durch...

MessageBox.Show(s1 + " | " + s2);
	 		
for (int i=0; i<s1.Length; i++)
{
  if (i ≥ s2.Length)
  {
    return 1;
  }
}
return -1;

... wohl richtig sortiert wird. Stimmst du mir bis hier überein? Ich habe dich bisher so verstanden als sollte ich erstmal die eigentliche länge des strings überprüfen. d.h. nen längerer string steht zwangsläufig unten. bis hier hin korrekt?

jetzt habe ich noch zusätzlich die "3.jpg" in das verzeichnis kopiert, diese steht aber jetzt vor der "1.jpg". sprich dafür habe ich noch keinen regelfall. wie soll ich das jetzt überprüfen? ...die zahl auslesen und die kleinere davon dann noch vorne?

also 1 heißt nach hinten und -1 nach hinten - ja?
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Hallo -acid-,

nur noch mal zur Sicherheit, wir sind erstmal dabei einen "normalen" String-Vergleich zu schreiben? Also muss man auch noch nicht unterscheiden, ob die Zeichen in den Strings Buchstaben oder Ziffern (oder was auch immer) sind. Ok soweit? Du solltest zur Klarheit deshalb erstmal Dateinamen ohne Ziffern verwenden. So entstehen weniger Missverständnisse.

Der Code, denn du jetzt geschrieben hast, ist eine gute Basis. Er berücksichtigt die jedoch bisher nur die Länge der Strings Außerdem gibst du bisher nur -1 oder 1 zurück. Die Strings können aber auch gleichlang sein (0).

Natürlich ist auch der reine Längenvergleich nicht ausreichend, denn abc.jpg soll ja vor z.jpg kommen, obwohl der erste String länger ist.

Du musst also noch den Inhalt der Strings zeichenweise (also in der Schleife) vergleichen. Hier kommen s1 und s2 ins Spiel.

HTH

herbivore
private Nachricht | Beiträge des Benutzers
-acid-
myCSharp.de - Member



Dabei seit:
Beiträge: 891
Herkunft: Hessen

beantworten | zitieren | melden

for (int i=0; i<s1.Length; i++)
{
  if (i ≥ s2.Length)
  {
    return 1;
  }
  else
  {
    if (s1[i] > s2[i])
    {
      return 1;
    }
    else
    {
      return -1;
    }
  }
}
return -1;

..liefert:

10.jpg
1.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
8.jpg
9.jpg

komischer weise ist plötzlich die 10 als erstes *aufm schlauch steht*
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Hallo -acid-,

vorne weg: ich habe den Code mal so umgestellt, dass wir weniger Zeilen brauchen, gerade wenn wir noch den "natürlichen" Vergleich einbauen, wird das sonst nicht mehr handelbar.


for (int i=0; i<s1.Length; i++) {
  if (i ≥ s2.Length)  {
    return 1;
  }
  if (s1[i] > s2[i])  {
    return 1;
  }
  return -1;
}
return -1;
Wenn man return benutzt, kann - und sollte(!) - man sich das else sparen. Jetzt siehst du bestimmt auch klarer, dass deine Schleife maximal einmal durchlaufen wird.

Soweit bist du auf dem richtigen Weg. Es fehlen zwei Fälle:

1. Die strings sind insgesamt gleich lang.
2. Die momentan zu vergleichenden Zeichen sind gleich.

herbivore

PS: Wenn es nach mir geht, kommen sogar die returns noch auf die Zeile mit dem if.


for (int i=0; i<s1.Length; i++) {
  if (i ≥ s2.Length)  { return 1; }
  if (s1[i] > s2[i])  { return 1; }
  return -1;
}
return -1;
private Nachricht | Beiträge des Benutzers
-acid-
myCSharp.de - Member



Dabei seit:
Beiträge: 891
Herkunft: Hessen

beantworten | zitieren | melden

geht sogar noch kürzer, indem man die klammern weglässt *g*
ok aber ich kann dir eh nix vormachen, wenns nach mir ging hätte ich dich schon längst zum moderator gemacht

for (int i=0; i<s1.Length; i++)
{
  if (i ≥ s2.Length) return 1;
  if (s1[i] > s2[i]) return 1;
  if (s1[i] == s2[i]) return 1; // macht die sortierung noch besser
  if (s1.Length == s2.Length) return 1; // verwürfelt die sortierung komplett
  return -1;				
}
return -1; 

also habe ich dich wohl bei punkt 2 falsch verstanden oder falsch angewendet.
private Nachricht | Beiträge des Benutzers
-acid-
myCSharp.de - Member



Dabei seit:
Beiträge: 891
Herkunft: Hessen

beantworten | zitieren | melden

sorry... wer lesen kann ist klar im vorteil.

for (int i=0; i<s1.Length; i++)
{
  if (i ≥ s2.Length) return 1;
  if (s1[i] > s2[i]) return 1;
  if (s1[i] == s2[i]) return 1;
  if (s1 == s2) return 1;
  return -1;
}
return -1; 

so ich denke jetzt habe ich das erfüllt was du wolltest.

sortierung sieht aus wie folgt:

1.jpg
10.jpg
2.jpg
3.jpg
4.jpg
5.jpg
6.jpg
7.jpg
8.jpg
9.jpg
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Hallo -acid-,

ganz ohne Klammern sparrt ja keine Zeilen mehr, verursacht aber bei späteren Programmänderungen nur (potentielle) Probleme.

Dein Code wird immer kompletter! Trotzdem möchte ich dich bitten, nicht einfach versuchsweise Anweisungen hinzuschreiben und zu probieren, ob richtig sortiert wird (Stichwort "macht die sortierung noch besser", "verwürfelt die sortierung komplett"), sondern mal wirklich versuchen zu überlegen, was dein Code macht (dazu kannst du das Programm im Kopf schnittweise durchspielen).

Dann fällt dir bestimmt auch auf, dass du zu keinem Zeitpunkt 0 zurückgibst, was aber die Rückgabe für komplett gleiche Strings ist. Ich kann dir verraten, dass die letzte (oder zumindest fast die letzte) Anweisung der fertigen Sortierroutine 'return 0;' sein wird, denn das die Strings in jeder Beziehung komplett gleich sind, weiß man eben erst (fast) am Ende, wenn man bis dahin keinen Unterschied gefunden hat.

Desweiteren gibst du einen Wert (und dann auch noch 1) zurück, sobald zwei Zeichen gleich sind. Das haut nicht hin. Wenn zwei Zeichen gleich sind, weiß man nur, dass man eben weitersuchen muss.

Und was die Längengleichheit angeht. Die kannst und solltest du erst feststellen, wenn auch alle Zeichen bis zum Ende eines der Strings gleich sind. Wenn dann auch noch beide Strings gleich sind, dann sind beide Strings insgesamt gleich (return 0) und wenn nicht, ist eben der zweite größer (return -1).

herbivore
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Hallo -acid-,

auch wenn deine Überarbeitung jetzt "richtig" sortiert, gilt quasi noch alles, was ich zu dem beitrag davor geschrieben habe. (Sie sortiert nur zufällig richtig).

Abgesehen davon, ist Sortieren lassen keine gute Methode, eine Vergleichsroutine zu testen. Du solltest stattdessen, die Vergleichsroutine direkt mit Beispielwerten aufrufen und das Ergebnis ausgeben. Probiere dabei mindestes das:

0 = MyClass.NatCompare ("a", "a")
0 = MyClass.NatCompare ("aa", "aa")
-1 = MyClass.NatCompare ("a", "b")
-1 = MyClass.NatCompare ("aa", "ab")
-1 = MyClass.NatCompare ("a", "aa")
1 = MyClass.NatCompare ("b", "a")
1 = MyClass.NatCompare ("ab", "aa")
1 = MyClass.NatCompare ("aa", "a")

herbivore
private Nachricht | Beiträge des Benutzers
-acid-
myCSharp.de - Member



Dabei seit:
Beiträge: 891
Herkunft: Hessen

beantworten | zitieren | melden

bin zwar noch nicht komplett drauf gekommen, aber ich glaube mir wird es immer klarer.

for (int i=0; i<s1.Length; i++)
{
  if (i ≥ s2.Length) return 1;
  if (s1[i] > s2[i]) return 1;
 
  if (s1.Length < s2.Length) return -1; // könnte man auch weglassen oder? weil es wird ja eh -1 am ende ausgegeben.
  if (s1.Length > s2.Length) return 1;
  if (s1 == s2) return 0;					
  
  return -1;
}


ich bekomme jetzt:

0 = MyClass.NatCompare ("a", "a") ok
0 = MyClass.NatCompare ("aa", "aa") ok
-1 = MyClass.NatCompare ("a", "b") ok
-1 = MyClass.NatCompare ("aa", "ab") ok
-1 = MyClass.NatCompare ("a", "aa") ok
1 = MyClass.NatCompare ("b", "a") ok
1 = MyClass.NatCompare ("ab", "aa") -1
1 = MyClass.NatCompare ("aa", "a") ok
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Hallo -acid-,

deine Schleife wird immernoch nur max. einmal durchlaufen. Wenn die Zeichen aber gleich sind, muss sie öfter durchlaufen werden. Dafür muss sie nicht nur bei 's1 > s2', sondern auch bei 's1 < s2' verlassen werden (jetzt mit -1).

Was die String-Längen angeht, musst (und darfst) du diese in der Schleife gar nicht weiter betrachten, denn mit 'i<s1.Length' in der for-Schleifen-Bedingung ist sichergestellt, dass du bei s1 noch nicht am Ende bist und mit 'i ≥ s2.Length' ist sicher gestellt, dass wenn s2 zu Ende ist, die Vergleichsroutine auch korrekt verlassen wird.

Nochmal: Die Stringlänge interessiert erst am Schluss. Erst wenn man am Ende von s1 angekommen ist (und alle Zeichen bis dahin gleich waren) interssiert, ob s2 noch ein Stück länger ist oder nicht.

Das soviele Werte beim Test stimmen, ist übrigens (leider) Zufall.

Aber weit bis zum Ziel ist es trotzdem nicht mehr.

herbivore
private Nachricht | Beiträge des Benutzers
-acid-
myCSharp.de - Member



Dabei seit:
Beiträge: 891
Herkunft: Hessen

beantworten | zitieren | melden

achso ok. dachte schon für was dann i≥s1.length da ist.

ok wenn ich dich richtig verstanden habe, sollte das so in die richtige richtung gehen...

for (int i=0; i<s1.Length; i++)
{
  if (i ≥ s2.Length) return 1;
  if (s1[i] > s2[i]) return 1;
  if (s1[i] < s2[i]) return -1;
  return -1;
}
if (s1.Length < s2.Length) return -1;
if (s1.Length > s2.Length) return 1;
if (s1 == s2) return 0;	
return -1; 

sie läuft 1x durch. mh. eigentlich müsste ich doch dann noch s1 == s2 nutzen?!
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Hallo -acid-,

die Version ist jetzt schon nahe dran. Deshalb schreib ich mal direkt, was noch zu ändern ist.


for (int i=0; i<s1.Length; i++)
{
  if (i ≥ s2.Length) return 1;
  if (s1[i] > s2[i]) return 1;
  if (s1[i] < s2[i]) return -1;
  // das return -1; muss weg, denn du weißt, an dieser Stelle, dass 
  // die beiden aktuellen Zeichen *gleich* sind. Da der String noch nicht 
  // zu Ende ist (bzw. man das zumindest hier noch nicht weiß), kannst du 
  // eben auch noch nichts zurückgeben, weil du eben noch nicht weiß
  // was noch kommt und welcher String größer oder kleiner ist, oder ob 
  // sie gleich sind. Wenn Du das return -1; wegnimmst, ann auch 
  // endlich deine Schleife mehrmals durchlaufen werden.
}
if (s1.Length < s2.Length) return -1;

// die abfrage 'if (s1.Length > s2.Length) return 1;' ist ok, aber überflüssig, 
// wenn s1 länger als s2 ist, dann wurde die Routine schon oben in der Schleife
// bei 'if (i ≥ s2.Length) return 1;'verlassen 

// 'if (s1 == s2) return 0;' naja, '==' für Strings benutzen ist gemogelt. Die
// Schleife oben hat schon gezeigt, dass alle Zeichen von s1 mit denen in s2
//  übereinstimmen. Wenn jetzt die Strings auch noch gleich lang sind,
// dann sind sie eben insgesamt völlig gleich, also reicht:
if (s1.Length == s2.Length) { return 0; }

return -1;
Wenn ich jetzt nicht geschudert habe, müsste es das erstmal sein
herbivore

PS: Ich muss jetzt bald mal weg und bin erst zwischen 20 und 21 Uhr wieder da.
private Nachricht | Beiträge des Benutzers
-acid-
myCSharp.de - Member



Dabei seit:
Beiträge: 891
Herkunft: Hessen

beantworten | zitieren | melden

ok chef. bis dahin erstmal nen dickes danke.

bekomme überall "ok" heraus. auch die schleife läuft mehrmals durch.

frage:
wäre "if (s1.Length == s2.Length) return 0;" nicht unnötig, weil es kann meiner meinung nach keine zwei gleichen strings geben?!

so jetzt muss ich also anfangen, auf zahlen im string zu überprüfen, wenn ich dic richtig verstanden habe. habe dazu folgende idee:

1. char array mit 10 elementen (0-9)
2. in der schleife mit indexofany überprüfen, ob ein element von array enthalten ist.
3. mir die zahl die ich entdeckt habe zu merken und mit der anderen vergleichen und die größere gewinnt.

joa soviel zu meiner idee *g*
(habe nämlich deine erklärung zu anfang nicht ganz verstanden.)
private Nachricht | Beiträge des Benutzers
herbivore
myCSharp.de - Experte

Avatar #avatar-2627.gif


Dabei seit:
Beiträge: 52329
Herkunft: Berlin

Themenstarter:

beantworten | zitieren | melden

Hallo -acid-,

zwei identische Strings können durchaus vorkommen. Erstmal schreiben wir ja allgemeine eine Vergleichsfunktion. Das diese Funktion für eine Sortierung von Dateien verwendet werden soll, ist klar, aber nur ein möglicher Verwendungszweck. In meinen Testfällen kommen z.B. identische Strings vor und auch beim Sortieren kann mehrmals der gleiche Strings vor kommen (z.B. Sortieren nach Interpret bei deiner MP3 Sammlung).

Das mit dem IndexOf könnte man machen, passt aber nicht gut zu dem, was wir bisher haben. Stattdessen muss man in der Schleife einfach gucken, ob s1 *und* s2 beides Ziffern sind (char.IsDigit-Methode), denn nur Zahlen, die an der *gleichen* Stelle in den Strings anfangen interessieren uns ja (und sie interessiern auch nur dann, wenn alle Zeichen vor den Zahlen in beiden Strings gleich sind).

Wenn man nun den Anfang einer Zahl gefunden hat, muss man erstmal die Länge der Zahl ermitten (Teilaufgabe: wie macht man das?). Wenn die Zahlen unterschiedlich lang sind, gibt es wieder ein return 1 bzw return -1. Ansonsten müssen wir die Zahlen zeichenweise vergleichen, als wären es Buchstaben (bzw. irgendwelche anderen Zeichen), also quasi die Schleife normal weiter durchlaufen lassen. Führende Nullen ignorieren wir bei diesem Anzatz erstmal. Die kommen später dazu.

Die Idee, wenn wir auf zwei Zahlen stoßen, die an der selben Stelle anfangen, ist, dass wir dann die Größe der Zahlen vergleichen müssen. Das machen wir in den zwei beschrieben Schritten: 1. Längenvergleich und evtl. 2. zeichenweisen Vergleich.

Beispiel 1. Fall: 1000 ist größer als 256, weil 1000 länger ist als 256
Beispiel 2. Fall: 2581 ist größer als 2567, weil die 8 größer ist als die 6 und die Ziffern davor gleich sind

Dann mal ran!

herbivore
private Nachricht | Beiträge des Benutzers