Entwickler-Ecke

Basistechnologien - Listen Sortier Problem


coolace - So 24.08.08 22:52
Titel: Listen Sortier Problem
Hy,

ich hab folgendes Problem was ich irgendwie nicht hinbekomme.
Ich habe eine Klasse daten die enthält den Member Datetime mit get und set Block.
Ich verwende in der Hauptform eine List<daten> Arrayliste.
Ich ruf die in der Hauptform mit liste.sort(new datumscompare()); auf.
Ich hab eine extra Klasse Icomparer angelegt siehe unten.
Das Problem ist er kompeliert das nicht mal.
Was mach ich falsch ?

C#-Quelltext
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:
using System;
using System.Collections.Generic;
using System.Text;

namespace WindowsApplication1
{
    public class datumscompare : IComparable
    {
        public int Compare(object x, object y)
        {
            if ((x is daten) & (y is daten))
            {
                daten k1 = x as daten; //castet er
                daten k2 = y as daten;
                return (k1.Gebdatum.CompareTo(k2.Gebdatum));
            }
            // else MessageBox.Show(this, "Falsch", "Fehler", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }


        #region IComparable Member

        public int CompareTo(object obj)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion

        #region IComparable Member

        int IComparable.CompareTo(object obj)
        {
            throw new Exception("The method or operation is not implemented.");
        }

        #endregion
    }
}


Dank und Gruß

Coolace


Moderiert von user profile iconChristian S.: Topic aus WinForms verschoben am So 24.08.2008 um 22:55


Christian S. - So 24.08.08 22:54
Titel: Re: Listen Sortier Problem
user profile iconcoolace hat folgendes geschrieben:
Das Problem ist er kompeliert das nicht mal.
Verrätst Du uns auch die Fehlermeldung ;-)


Kha - Mo 25.08.08 13:57

user profile iconcoolace hat folgendes geschrieben:
Ich hab eine extra Klasse Icomparer angelegt siehe unten.
Hast du nicht, schau noch mal nach. Was du implementiert hast, ist IComparable ;) .
Wenn es aber ein einmaliger Aufruf ist, würde ich eher zu der Überladung mit Delegate-Parameter tendieren:

C#-Quelltext
1:
2:
3:
4:
5:
6:
int CompareDaten(daten x, daten y) // Klassennamen bitte groß schreiben
{
  return x.Gebdatum.CompareTo(y.Gebdatum);
}
[...]
list.Sort(CompareDaten);

Oder wenn du's gern kurz und spritzig hast (C# 3.0):

C#-Quelltext
1:
list.Sort((x, y) => x.Gebdatum.CompareTo(y.Gebdatum));                    


coolace - Mo 25.08.08 21:30

Hy,

nachdem es nicht hingehauen hab hab ich diese extra Klasse gelöscht und folgendes probiert da ich mit
der ersten Geschichte irgendwie auf dem Holzweg war.

C#-Quelltext
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:
using System;
using System.Collections.Generic;
using System.Text;

namespace WindowsApplication1
{
    public class daten : IComparable
    {
        string gebname;
        DateTime gebdatum;

        public string Gebname
        {
            get { return gebname; }
            set { gebname = value; }
        }

        public DateTime Gebdatum
        {
            get { return gebdatum; }
            set { gebdatum = value; }
        }

        public override string ToString()
        {
           string s = gebdatum.ToShortDateString() + " " + gebname;
           return s;
        }

        public string Alter()
        {
            string age = Convert.ToString(DateTime.Now.Year - gebdatum.Year);
            return age;
        }

        public int CompareTo(object obj)
        {
            if (obj is daten)
            {
                daten d = (daten)obj;
                return Gebdatum.CompareTo(d.Gebdatum);
            }
            else return -1;
        }
    }
}

Hauptprogramm
nur noch liste.sort();

Gesagt getan Fehlermeldung weg aber sortieren tut er trotzdem nicht, ich würd diese Sortfunktion echt gern verstehen da Sie wichtig ist

LG

Coolace


lothi - Di 26.08.08 09:18

Hallo

Das Beispiel bei dir sieht gut aus.
Wie rufst du denn das auf? Ein einzelner Wert kannst du ja nicht Sortieren.
In dem du jetzt in der Klasse IComparable Schnittstelle drin hast kannst du die Klasse in einer List<datumscompare> sortieren.

Ausserdem sollstest du noch den Fall wenn obj null ist abfangen

Vielleicht hilft ja das weiter:

http://www.galileocomputing.de/openbook/visual_csharp/visual_csharp_05_003.htm#mjb3469db33024a1c67fec977e0ab1b8b9


coolace - Di 26.08.08 10:01

Hy,

danke für deine Hilfe, ich füge die Elemente in der Form1 mit daten.add(p) hinzu und
zum Schluss mach ich nur noch List.Sort()

Hab das so in dem Beispiel hier nach langem suchen gefunden
http://codebetter.com/blogs/david.hayden/archive/2005/02/27/56099.aspx

aber irgendwie klappt das nicht muss ich bei list.sort noch irgendwas übergeben ?


lothi - Di 26.08.08 12:18

Hallo

Du kannst mir daten.Add() keine Liste erstellen. Dafür müsstest du noch ein Schnittstellen hinzufügen. z.B IList.

Aber in deinem Fakk kannst du direkt mit List<T> arbeiten. Hier ein Beispiel:

C#-Quelltext
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:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
using System;  
using System.Collections.Generic;  
using System.Text;  

 
namespace WindowsApplication1  
{  
  
    public class Start
    {
      public static void Main()
      {
        List<daten> li = new List<daten>();
       li.Add(new daten(new DateTime(2001,5,20)));
        li.Add(new daten(new DateTime(2001,5,21)));
        li.Add(new daten(new DateTime(2001,5,19)));
        li.Add(new daten(new DateTime(2001,5,23)));
        li.Add(new daten(new DateTime(2001,5,13)));
        
        Console.WriteLine("Unsortierte Liste");
        Console.WriteLine("***********************************");
        foreach(daten d in li)
        {
          Console.WriteLine(d.ToString());
        }
        
        Console.WriteLine("Sortierte Liste");
        Console.WriteLine("***********************************");
        li.Sort();
        foreach(daten d in li)
        {
          Console.WriteLine(d.ToString());
        }
      }
    }
    public class daten : IComparable  
    {  
        string gebname;  
        DateTime gebdatum;  

        public daten(DateTime dat)
        {
          gebdatum = dat;
        }
        public string Gebname  
        {  
            get { return gebname; }  
            set { gebname = value; }  
        }  

 
        public DateTime Gebdatum  
        {  
            get { return gebdatum; }  
            set { gebdatum = value; }  
        }  

 
        public override string ToString()  
        {  
           string s = gebdatum.ToShortDateString() + " " + gebname;  
           return s;  
        }  

 
        public string Alter()  
        {  
            string age = Convert.ToString(DateTime.Now.Year - gebdatum.Year);  
            return age;  
        }  

 
        public int CompareTo(object obj)  
        {  
            if (obj is daten)  
            {  
                daten d = (daten)obj;  
                return Gebdatum.CompareTo(d.Gebdatum);  
            }  
            else return -1;  
        }  
    }  
}


coolace - Di 26.08.08 13:33

sorry, war etwas unglücklich formuliert natürlich mach ich es so sonst geht die .Add funktion ja auch nicht

C#-Quelltext
1:
2:
List<daten> li = new List<daten>();  
li.Add(new daten(new DateTime(2001,5,20)));

Hab nochmal alles überprüft und die Klasse stimmt, nur glaub ich das er aus irgendwelchen Gründen die unsortiert und nicht sortiert ausgibt.

Kleine Verständnisfrage: bei meiner Hauptform ist es so das er jedesmal wenn ich die Dateneingebe das so ist

C#-Quelltext
1:
2:
3:
List<daten> li = new List<daten>();  
li.Add(new daten(new DateTime(2001,5,20)));  
li.Sort();


kann es sein das er die dann beim Speichern in die XML Datei nicht Sortiert speichert bzw. unsortiert beim Einlesen ausgibt??

LG


lothi - Di 26.08.08 13:50

Hallo

Also wir uns beide einig das deine Klasse mit der sortiert funktioniert. Habe ja nur dein Beispiel kopiert. Ich glaube das liegt ganz in einem andern Ort:

Zitat:

kann es sein das er die dann beim Speichern in die XML Datei nicht Sortiert speichert bzw. unsortiert beim Einlesen ausgibt??


Wenn du die Daten nicht richtig übergibst dann ja. Aber dazu muss wissen, man wie du die Daten in die XML Datei schreibst.
Wie du in meiner Consolen Ausgabe siehst, stimm die Listenausgabe.


coolace - Di 26.08.08 14:11

werd heut Abend mal das Hauptprogramm posten. Ich komm irgendwie nicht drauf was ich falsch mach

Vielen Dank und Gruß

Coolace


coolace - Di 26.08.08 21:26

mein Hauptprogramm, ich hab nachgesehen und in der .xml datei speichert er die Korrekt, muss also beim auslesen sein


C#-Quelltext
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:
public void Eintragadd(string sd, DateTime date)
        {
            daten d = new daten();
            d.Gebname = sd;
            d.Gebdatum = date;
            liste.Add(d);
            liste.Sort();
            liste.TrimExcess();
            lbox.Items.Clear();
            foreach (daten temp in liste)
            {
                lbox.Items.Add(temp.ToString());
            }
            
      }

        //Auswahl der richtigen Person und anzeige in der Listbox
        public void Geburtstagskind()
        {
            Int32 i = 0;
            DateTime aktuell = DateTime.Now;
            foreach (daten temps in liste)
            {
                lbox.Items.Add(temps.ToString());
            }

            foreach (daten tempi in liste)
            {
                if (tempi.Gebdatum.Month >= aktuell.Month)
                {
                    if (tempi.Gebdatum.Month <= liste[i + 1].Gebdatum.Month)
                    {
                        if (tempi.Gebdatum.Day <= liste[i + 1].Gebdatum.Day)
                        {
                            txtage.Text = tempi.Alter();
                            txtgeburtstag.Text = tempi.Gebname;
                            break;
                        }
                    }
                }
                i++;
            }
            
        }


lothi - Di 26.08.08 21:53

ich sehe nirgends das du was auswähltst. In der ersten Methode fügst du 1 Datum und Name der Liste hinzu und schreibst das in die Listbox.

Bei der 2. weiss ich nicht genau was du da machst i ist zum Beispiel immer 0.
Du vergleichst immer ein Geburtsdatum mit dem 2. Geburtsdatum aus der gleichen Listen aktuell benutzt du nirgends.


coolace - Di 26.08.08 21:58

in der ersten Methode füge ich Datums hinzu mittels einem Modalen Dialog.

in der 2 Methode versuch ich dann zu ermitteln wer das aktuelle Geburtstagsperson ist und füg die dann in der Hautpform in das entsprechende Feld. Mein Problem ist aber nur er gibt die Liste, warum auch immer unsortiert aus


Kha - Di 26.08.08 22:01

Warum füllst du in beiden Methoden die ListBox? Sicher, dass in der zweiten liste sortiert ist?
Mach es doch bitte so:
  1. Alle "daten" in die Liste schreiben
  2. Sortieren
  3. In die ListBox übertragen

Und das ganze einmal im gesamten Programm.

In deiner letzten Schleife kannst du auch einfach
if (temps.Gebdatum >= aktuell) { [...] break; }benutzen.

@lothi: Da steckt noch ein i++ in der Schleife.


lothi - Di 26.08.08 22:05

Ja aber ich sehe in beiden Codes nirgends wo du die Liste füllst. Nur ein Code in dem du ein einziger DS in die Liste einliest.


C#-Quelltext
1:
2:
3:
4:
daten d = new daten();  
            d.Gebname = sd;  
            d.Gebdatum = date;  
            liste.Add(d);


Ich auch nirgends wo du irgenwas aus einer XML liest

@Kah
Ja jetzt wo du's sagst!

Moderiert von user profile iconChristian S.: Highlight- durch C#-Tags ersetzt


coolace - Di 26.08.08 22:20

hy,

hab das ganze Projekt mal hochgeladen .

Moderiert von user profile iconChristian S.: Link auf Download-Seite durch Anhang ersetzt

Hier sieht man das Elend am besten .

Danke und Gruß

Coolace


lothi - Mi 27.08.08 15:35

Hallo

Ich glaube ich sehe jetzt das Problem.
Deine Liste wird nicht nach Datum sortiert sonder nach einem String.

Darum passiert das hier:

6.8.08
7.5.08
12.8.05
13.8.08

Da ich ja selber nicht gerade der Hirsch bin muss ich mir das am abend im Debugger mal näher anschauen. Hier auf der Arbeit habe ich kein VS.

Gruss Lothi


Kha - Mi 27.08.08 16:02

Wozu eine Listbox sortieren, die von einer sortierten Liste befüllt wird :nixweiss: ?
Zitat:
Use the Sorted property to automatically sort strings alphabetically in a ListBox


lothi - Mi 27.08.08 16:13

Hallo Kah

Gar nicht nicht. Aber wenn ich seinen Code ansehe serialisiert er die Klasse daten mit einem XMLSerialiser und liest diese wieder in eine neue Liste ein.
Ich vemute jetzt mal das er daten.ToString() serialisiert und dann die Liste dach diesem string sortiert wird und nicht nach dem Datum.
Wie gesagt ist eine reine vermutung von mir. Habe sein Programm ausprobiert und die ListBox wird nach string sortiert. Habe aber den Code noch nicht genau angeschaut.

Gruss Lothi


Kha - Mi 27.08.08 17:26

Das war nicht als Antwort auf deinen Post gedacht, hätte ich vielleicht deutlicher machen sollen. Seine Listbox ist auf "Sorted = true" eingestellt.


lothi - Mi 27.08.08 18:52

Ich habe deinen Post als hilfe und Bereicherung angesehen und nicht als Einmischung.
Ich wäre jetzt nie auf die Idee gekommen zu schauen od bei der Listbox die Eigenschaft Sorted auf true steht. Da brauch ich kaum mehr weiter zu suchen.


coolace - Mi 27.08.08 20:57

Hy,

vielen vielen Dank, das war des Rätsellösung, diese Sorted True geschichte hat wieso auch immer meinen IComparer ausser Kraft gesetzt

Danke und Gruß

Coolace