Forum: PC-Programmierung c# Ermittel das zweithöchste Datum einer List<DateTime>


von csharper (Gast)


Lesenswert?

Hallo!

Ich versuche verzweifelt das zweitweit entfernteste Datum einer Liste 
mit Daten zu ermitteln.

Folgenden Code habe ich dafür geschrieben:
1
 public static DateTime SecondWarrantyDate(List<DateTime> Warrantys)
2
        {
3
            Warrantys.Sort();
4
5
            DateTime _SecondWarrantyDate = new DateTime();
6
            _SecondWarrantyDate = DateTime.MinValue;
7
            DateTime dummy = new DateTime();
8
            dummy = DateTime.MinValue;
9
            bool foundsecond = false;
10
            bool firstround = true;
11
            foreach (DateTime dt in Warrantys)
12
            {
13
                Console.WriteLine("Funktionsinhalt -> " + dt.ToString());
14
                //Kleiner als 0 (null) 
15
                //Diese Instanz liegt vor value.
16
                //Zero 
17
                //Diese Instanz entspricht value. 
18
                //Größer als 0 (null) 
19
                //Diese Instanz liegt nach value, oder value ist null.
20
                if ((dummy.CompareTo(dt) < 0) && firstround)
21
                {
22
                    dummy = dt;
23
                    firstround = false;
24
                }
25
26
                if ((dummy.CompareTo(dt) < 0) && !firstround && !foundsecond)
27
                {
28
                    foundsecond = true;
29
                    _SecondWarrantyDate = dt;
30
                }
31
            }
32
33
34
35
            return _SecondWarrantyDate;
36
        }

Wenn ich die Funktion mit diesen Daten befeuere, funktioniert sie:
1
 List<DateTime> dtlist = new List<DateTime>();
2
               dtlist.Add(DateTime.Now);
3
               dtlist.Add(DateTime.Now.AddYears(5));
4
               dtlist.Add(DateTime.Now.AddYears(10));
5
               dtlist.Add(DateTime.Now.AddYears(10));
6
                dtlist.Add(DateTime.Now.AddYears(6));
7
8
              Console.WriteLine("SecondWarrantyDate:");
9
               Console.WriteLine(SecondWarrantyDate(dtlist).ToString());

Aber leider nicht, wenn ich folgende Daten benutze, welche mir die 
Dell-Schnittstelle mit Garantiedaten zurückliefert...

->
1
14.10.2015 00:00:00
2
14.10.2015 00:00:00
3
14.10.2015 00:00:00
4
01.05.2022 00:00:00

Mein Verdacht: Die Funktion datetime.compareto() vergisst das Jahr beim 
Vergleich?!

Kann mir jemand einen Tipp geben?

Gruß!

von bluppdidupp (Gast)


Lesenswert?

Wäre es nicht einfacher, die Liste einfach mit .Sort() aufsteigend zu 
sortieren und dann einfach das zweite Element aus der sortierten Liste 
zu ziehen?
(und bei Bedarf ggf. noch Duplikate vor dem Sortieren entfernen)

von csharper (Gast)


Lesenswert?

bluppdidupp schrieb:
> Wäre es nicht einfacher, die Liste einfach mit .Sort() aufsteigend
> zu
> sortieren und dann einfach das zweite Element aus der sortierten Liste
> zu ziehen?
> (und bei Bedarf ggf. noch Duplikate vor dem Sortieren entfernen)

Sicher eine Möglichkeit, aber wie lösche ich denn ohne weiteres alle 
Duplikate aus einer Liste?

List.RemoveDuplicateEntrys() gibt es jedenfalls nicht, also müsste ich 
mir die Logik wohl selber schreiben?

Und dann ist es auch wieder nur ein anderer Lösungsansatz, der ähnlich 
viel Aufwand benötigt.

von bluppdidupp (Gast)


Lesenswert?

Also z.B. so irgendwie:
1
// Input:
2
List<DateTime> inputDates=new List<DateTime>();
3
inputDates.Add(new DateTime(2015,10,14));
4
inputDates.Add(new DateTime(2015,10,14));
5
inputDates.Add(new DateTime(2015,10,14));
6
inputDates.Add(new DateTime(2022,5,1));
7
8
// Doppelte Werte entfernen:
9
List<DateTime> inputDatesDistinct=inputDates.Distinct().ToList();
10
11
// Aufsteigend sortieren:
12
inputDatesDistinct.Sort();
13
14
// Ausgeben:
15
if (inputDatesDistinct.Count>0)
16
{
17
    Console.WriteLine("Liegt am längsten zurück: "+inputDatesDistinct[0]);
18
}
19
20
if (inputDatesDistinct.Count>1)
21
{
22
    Console.WriteLine("Liegt am zweit-längsten zurück: "+inputDatesDistinct[1]);
23
}

von Thomas Z. (thomas_z41)


Lesenswert?

Bist du dir sicher dass dein Datumsformat richtig geparsed wird?

von csharper (Gast)


Lesenswert?

Thomas Z. schrieb:
> Bist du dir sicher dass dein Datumsformat richtig geparsed wird?

Jop, folgender Code ergibt:
1
foreach (DateTime dt in Warrantys)
2
            {
3
              Console.WriteLine("Jahr->" + dt.Year);
4
              Console.WriteLine("Monat->" + dt.Month);
5
              Console.WriteLine("Tag->" + dt.Day);
6
...
7
...

->

Jahr->2015
Monat->10
Tag->14
...
Jahr->2022
Monat->5
Tag->1

von csharper (Gast)


Lesenswert?

bluppdidupp schrieb:
> Also z.B. so irgendwie:// Input:
> List<DateTime> inputDates=new List<DateTime>();
> inputDates.Add(new DateTime(2015,10,14));
> inputDates.Add(new DateTime(2015,10,14));
> inputDates.Add(new DateTime(2015,10,14));
> inputDates.Add(new DateTime(2022,5,1));
>
> // Doppelte Werte entfernen:
> List<DateTime> inputDatesDistinct=inputDates.Distinct().ToList();
>
> // Aufsteigend sortieren:
> inputDatesDistinct.Sort();
>
> // Ausgeben:
> if (inputDatesDistinct.Count>0)
> {
>     Console.WriteLine("Liegt am längsten zurück:
> "+inputDatesDistinct[0]);
> }
>
> if (inputDatesDistinct.Count>1)
> {
>     Console.WriteLine("Liegt am zweit-längsten zurück:
> "+inputDatesDistinct[1]);
> }

Deine Lösung hat ebenfalls das selbe Programm... ich verstehe nicht 
warum...

Dann muss es ja an DateTime.Sort() liegen?!

von csharper (Gast)


Lesenswert?

Programm = Problem.

von csharper (Gast)


Lesenswert?

Ja, es lag an List.Sort()...

inputDatesDistinct.Sort((a, b) => b.CompareTo(a));

Damit funktioniert es.

Danke für eure Bemühungen.

von csharper (Gast)


Lesenswert?

csharper schrieb:
> Ja, es lag an List.Sort()...
>
> inputDatesDistinct.Sort((a, b) => b.CompareTo(a));
>
> Damit funktioniert es.
>
> Danke für eure Bemühungen.

Sorry, hab mich zu früh gefreut... das macht gar keinen Sinn, daran 
liegt es nicht. Ich hab die Liste nur in der anderen Reihenfolge 
abgegriffen...

Ich weiß immer noch nicht, warum es nicht funktioniert. Hat noch jemand 
einen Tipp?

von Fuzzi59 (Gast)


Lesenswert?

csharper schrieb:
> Sorry, hab mich zu früh gefreut... das macht gar keinen Sinn, daran
> liegt es nicht. Ich hab die Liste nur in der anderen Reihenfolge
> abgegriffen...

Und das ist auch richtig so! Wenn du nämlich aufsteigend sortierst und 
den zweiten Wert ausliest, erhälst du den zweitkleinsten Wert. 
Absteigend sortiert hingegen ist der zweite Wert auch der zweithöchste.

Ich schätze mal dein Problem entstand dadurch, dass du nur zwei 
verschiedene Werte genutzt hast und so bei falscher Sortierung den 
entsprechend falschen Wert erhalten hast.

von Arc N. (arc)


Lesenswert?

csharper schrieb:
> bluppdidupp schrieb:
>> Wäre es nicht einfacher, die Liste einfach mit .Sort() aufsteigend
>> zu
>> sortieren und dann einfach das zweite Element aus der sortierten Liste
>> zu ziehen?
>> (und bei Bedarf ggf. noch Duplikate vor dem Sortieren entfernen)
>
> Sicher eine Möglichkeit, aber wie lösche ich denn ohne weiteres alle
> Duplikate aus einer Liste?
>
> List.RemoveDuplicateEntrys() gibt es jedenfalls nicht, also müsste ich
> mir die Logik wohl selber schreiben?
>
> Und dann ist es auch wieder nur ein anderer Lösungsansatz, der ähnlich
> viel Aufwand benötigt.
1
            List<DateTime> dtList = new List<DateTime>();
2
            dtList.Add(DateTime.Now);
3
            dtList.Add(new DateTime(2015, 10, 14, 0, 0, 0));
4
            dtList.Add(new DateTime(2015, 10, 14, 0, 0, 0));
5
            dtList.Add(new DateTime(2015, 10, 14, 0, 0, 0));
6
            dtList.Add(new DateTime(2015, 10, 14, 0, 0, 0));
7
            dtList.Add(new DateTime(2015, 10, 14, 0, 0, 0));
8
            dtList.Add(DateTime.Now.AddYears(5));
9
            dtList.Add(DateTime.Now.AddYears(5));
10
            dtList.Add(DateTime.Now.AddYears(5));
11
            dtList.Add(DateTime.Now.AddYears(10));
12
            dtList.Add(DateTime.Now.AddYears(10));
13
            dtList.Add(DateTime.Now.AddYears(6));
14
15
            var sortedListOfDistinctDates = dtList.Distinct().OrderBy(date => date).ToList();

: Bearbeitet durch User
von csharper (Gast)


Lesenswert?

Fuzzi59 schrieb:
> csharper schrieb:
>> Sorry, hab mich zu früh gefreut... das macht gar keinen Sinn, daran
>> liegt es nicht. Ich hab die Liste nur in der anderen Reihenfolge
>> abgegriffen...
>
> Und das ist auch richtig so! Wenn du nämlich aufsteigend sortierst und
> den zweiten Wert ausliest, erhälst du den zweitkleinsten Wert.
> Absteigend sortiert hingegen ist der zweite Wert auch der zweithöchste.
>
> Ich schätze mal dein Problem entstand dadurch, dass du nur zwei
> verschiedene Werte genutzt hast und so bei falscher Sortierung den
> entsprechend falschen Wert erhalten hast.

Du hast Recht. :) Es funktioniert so, vielen Dank... ich war wohl so 
verzweifelt, dass ich gar nichts mehr geblickt habe.

Ich verstehe trotzdem nicht, warum mein Anfangscode nicht funktioniert 
hat...

Naja, manchmal soll mans einfach so hinnehmen.

Danke euch.

Arc N. schrieb:
> csharper schrieb:
>> bluppdidupp schrieb:
>>> Wäre es nicht einfacher, die Liste einfach mit .Sort() aufsteigend
>>> zu
>>> sortieren und dann einfach das zweite Element aus der sortierten Liste
>>> zu ziehen?
>>> (und bei Bedarf ggf. noch Duplikate vor dem Sortieren entfernen)
>>
>> Sicher eine Möglichkeit, aber wie lösche ich denn ohne weiteres alle
>> Duplikate aus einer Liste?
>>
>> List.RemoveDuplicateEntrys() gibt es jedenfalls nicht, also müsste ich
>> mir die Logik wohl selber schreiben?
>>
>> Und dann ist es auch wieder nur ein anderer Lösungsansatz, der ähnlich
>> viel Aufwand benötigt.
>             List<DateTime> dtList = new List<DateTime>();
>             dtList.Add(DateTime.Now);
>             dtList.Add(new DateTime(2015, 10, 14, 0, 0, 0));
>             dtList.Add(new DateTime(2015, 10, 14, 0, 0, 0));
>             dtList.Add(new DateTime(2015, 10, 14, 0, 0, 0));
>             dtList.Add(new DateTime(2015, 10, 14, 0, 0, 0));
>             dtList.Add(new DateTime(2015, 10, 14, 0, 0, 0));
>             dtList.Add(DateTime.Now.AddYears(5));
>             dtList.Add(DateTime.Now.AddYears(5));
>             dtList.Add(DateTime.Now.AddYears(5));
>             dtList.Add(DateTime.Now.AddYears(10));
>             dtList.Add(DateTime.Now.AddYears(10));
>             dtList.Add(DateTime.Now.AddYears(6));
>
>             var sortedListOfDistinctDates =
> dtList.Distinct().OrderBy(date => date).ToList();

Auch dir danke!

von Andreas E. (andreas_e_2)


Lesenswert?

Spontan und ungetestet könnte es auch so gehen
1
            var a = Warrantys.Distinct().OrderByDescending(b => b.Date).Skip(1).Take(1);
2
            return a.First();

von bluppdidupp (Gast)


Lesenswert?

Unter "zweitweit entfernteste" hätte ich eigentlich das Datum das am 
zweit-weitesten in der Vergangenheit liegt verstanden, daher hatte ich 
aufsteigend sortiert, dann liegt das kleinere Datum (=weiter in der 
Vergangenheit) vorne ;D

von Andreas E. (andreas_e_2)


Lesenswert?

Stimmt. Also nur OrderBy(b=> ...

sry, war noch nicht ganz wach.

von Georg (Gast)


Lesenswert?

csharper schrieb:
> Sicher eine Möglichkeit, aber wie lösche ich denn ohne weiteres alle
> Duplikate aus einer Liste?

Warum eigentlich? das 2. ist das 2. Und wenn das denselben Wert hat wie 
das 1. oder das 3., woher weisst du dann überhaupt, welches du jetzt 
löschen musst? Das ist nicht wirklich ein Problem der Software, sondern 
des Konzepts - was sind denn überhaupt Duplikate? Doppelgänger, geklonte 
Kunden oder was?

Georg

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.