Laden...

In Array den höchsten Wert unter 10er Blöcken ermitteln.

Erstellt von KuGBeginner vor 5 Jahren Letzter Beitrag vor 5 Jahren 1.899 Views
K
KuGBeginner Themenstarter:in
21 Beiträge seit 2015
vor 5 Jahren
In Array den höchsten Wert unter 10er Blöcken ermitteln.

Hallo an das Forum,

ich fülle myArray mit 20 unterschiedlichen Werten.
Mit myArray.Max kann ich den höchsten Wert des Arrays ermitteln.

Ich möchte jetzt aber nach 10 Werten den höchsten Wert der ersten 10 Werte und nach 20 Werten den höchsten Wert der letzten 10 Werte ermitteln. Bei meinen Versuchen habe ich es nur erreicht, den höchsten Wert aller 20 Werte zu ermitteln.

Die Variable, die den Maximalwert ausliest, auf 0 zu setzen brachte keinen Erfolg.
Wenn ich eine Kopie des ersten 10er Blocks und des zweiten 10er Blocks erstelle und die Kopie auswerte, erhalte ich wieder nur das Gesamtergebnis.
Ich habe bisher keine Lösung gefunden, myArrayMax an der Stelle 11 zu löschen....

Wie kann ich das Problem lösen?
Vielen Dank für die Unterstützung!

L
136 Beiträge seit 2015
vor 5 Jahren

Hallo KuGBeginner,

Da gibt es doch so einige Möglichkeiten 😁

1.
Das Ganze nicht mit array lösen sondern mit List<T>, welches dann Remove, RemoveAt oder RemoveRange zur Verfügung stellt.
Dann kannst Du die Listen auch sortieren und und und und...

2.
Mit LINQ arbeiten -> findest Du bestimmt haufenweise Treffer im Netz

3.
Funktion schreiben mit Maximalwertrückgabe
Dabei musst Du Dein Array und einen Startindex sowie z.B. Endindex übergeben...
Findest bestimmt selbst heraus wie das zu programmieren ist.

4.
Zwei Array mit der Grösse 10 erstellen (Index 0-9)
Durch Dein Array iterieren mit z.B. einer for schleife
Erstes Array[0-9] mit Deinem Array von [0-9] füllen
Zweites Array[0-9] mit Deinem Array von [10-19] füllen
auf dem Ersten und zweiten array den Maximalwert ermitteln

Als Gedankenstütze...

Zeig doch mal was Du schon hast

Gruss Lhyn

2.079 Beiträge seit 2012
vor 5 Jahren

Wozu unbedingt eine List? Die ist praktisch, hilft hier mMn. aber eher wenig. Klar kann man dann Elemente entfernen, aber das halte ich für den umständlichsten Weg, gleich nach der Option, eine eigene Methode zu schreiben 😄
Wobei Letzteres aber eine hervorragende Übung sein würde, also ist das vielleicht doch keine so schlechte Idee

Punkt 4:
Die Hälfte der Arbeit tut die CopyTo-Methode. Man braucht zwar immer noch ein Array mit Length=10, aber mit myArray.CopyTo kann man dann die Elemente in dieses neue Array schreiben. Ein zweite Length=10-Array braucht's aber nicht, man kann ja einfach das Vorherige verwenden.

Ich persönlich würde aber die LINQ-Variante bevorzugen, weil sich der ganze Code auf eine kurze und mMn. sehr leicht verständliche Zeile beschränkt. Tipp: "Skip" und "Take", wenn Du Englisch kannst, dürfte dir schon klar sein, was das tut 😉

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

C
2.121 Beiträge seit 2010
vor 5 Jahren

Die Variable, die den Maximalwert ausliest, auf 0 zu setzen brachte keinen Erfolg.

Den bisher ausgelesenen Maximalwert löschen ist in der Tat keine Lösung. Was könnte es bringen?

Wenn ich eine Kopie des ersten 10er Blocks und des zweiten 10er Blocks erstelle und die Kopie auswerte, erhalte ich wieder nur das Gesamtergebnis.

Das sollte aber funktionieren. Wie machst du es?

Ich habe bisher keine Lösung gefunden, myArrayMax an der Stelle 11 zu löschen....

Du kannst höchstens den Wert überschreiben aber nicht löschen. Was soll es bewirken?

Ich lese heraus dass du nicht unbedingt weißt was du da eigentlich tust.
Statt mit LINQ auf irgendwas zu schießen und immer noch nicht zu wissen was passiert, würde ich dazu raten es selbst anzugehen.
Mach dir eine Methode die das Array übergeben bekommt, den Startindex und die Anzahl der zu untersuchenden Werte. Sie bestimmt das Maximum dieser Werte.
Das dürfte ein 10- vielleicht 15-Zeiler werden, mehr nicht.

Wenn du verstanden hast was da passiert, kannst du dir überlegen wie du das in LINQ umsetzt.

3.003 Beiträge seit 2006
vor 5 Jahren

Vermutlich schnellste Lösung:


Methode FindeLokalesMaximum
Eingabe: Array von Werten, Größe der lokalen Gruppen (10 bei dir)
für einen zaehler von 0 bis zur größe des Zahlenarrays
  wenn der zaehler größer null und durch die Größe der lokalen Gruppe ohne Rest teilbar ist
     liefere das derzeitige maximum und setze es auf ersten wert der nächsten gruppe
  wenn der Wert des Arrays an der stelle des Zählers größer ist als das aktuelle lokale Maximum
     setze das lokale Maximum auf diesen Wert

am Ende: wenn die Länge des Zahlenarrays nicht ohne Rest durch die Größe der lokalen Gruppe teilbar ist
   liefere das zuletzt gesetzte lokale Maximum

Die eigentliche Methode in C# ist sogar noch kürzer. (4 Zeilen)
Schau dir https://docs.microsoft.com/de-de/dotnet/csharp/language-reference/keywords/yield an.
Einfach durch dein Array rennen und in regelmäßigen Abständen (bei dir alle 10 Werte) das lokale Maximum zurückgeben und danach zurücksetzen.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

6.911 Beiträge seit 2009
vor 5 Jahren

Hallo,

das ist ein Beispiel bei dem auch mit Span<T> gearbeitet werden kann.


public static IEnumerable<int> GetWindowedMax(this int[] source, int windowSize)
{
    int windows = source.Length / windowSize;

    for (int i = 0; i < windows; ++i)
    {
        Span<int> span = source.AsSpan(i * windowSize, windowSize);
        yield return GetMax(span);
    }
}

private static int GetMax(Span<int> span)
{
    int max = int.MinValue;

    for (int i = 0; i < span.Length; ++i)
    {
        if (span[i] > max) max = span[i];
    }

    return max;
}

(Code ohne Argument-Validierung und nicht optimiert).

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

K
KuGBeginner Themenstarter:in
21 Beiträge seit 2015
vor 5 Jahren

Ganz herzlichen Dank an das Forum für die zahlreichen Meldungen; ein solches Feedback ist außergewöhnlich!
Ich konnte mein Problem mittlerweile über linq ==> Skip und Take lösen! 😁

Gruß KuGBeginner

3.003 Beiträge seit 2006
vor 5 Jahren

Nur so als Nachtrag: ich bin sicher der erste, der die Benutzung von Linq in so einem Fall begrüßt, es sei nur darauf hingewiesen, dass Skip().Take(), so einfach es sein mag, grottenlangsam ist und superschlecht skaliert. Kommt drauf an, ob das für den Anwendungsfall wichtig ist (meistens nicht, aber in den Fällen, wo es drauf ankommt, tut's dann richtig weh...).

LaTino
Zur Illustration:

mit Skip.Take vs. die oben mit Pseudocode skizzierte Lösung
20 Elemente: Faktor 4 langsamer
20.000 Elemente: Faktor 225
200.000 Elemente: Faktor 1530
2.000.000 Elemente: Faktor 28850 (knapp 10 Minuten vs 20 ms)
Sollte man im Hinterkopf behalten.
(gfoidls Vorschlag ist nochmal einen Zacken schneller, schätze ich, skaliert aber nicht besser)

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)