Mittwoch, 11. Juni 2014

Erweitertes Any-Pattern

Hallo Leute!

Das letzte mal ist schon etwas her. Damals hatte ich euch das All- und Any-Pattern gezeigt. Heute geht es um eine Variante des Any-Patterns. Ihr erinnert euch. Zur Erinnerung... Das Any Pattern sah z.B. so aus:


int[] werte = new int[] { 4, 2, 7, 3, 5, 1, 8 };

boolean erfuellt = false;
for (int i = 0; i < werte.length; i++) {
  if (werte[i] > 5) {
    erfuellt = true;
    break;
  }
}
if (erfuellt) {
  System.out.println("Mindestens ein Wert ist größer als 5.");
}

Es dient dazu herauszufinden, ob irgendein ("Any") Element in einem Array eine bestimmte Bedingung erfüllt. In diesem Fall ob es größer als 5 ist.


Nun möchte man aber vielleicht auch noch wissen welches Element das ist, was diese Bedingung erfüllt. Auch diese Information kann man erhalten, indem man das Pattern leicht abwandelt. Der boolean erfuellt wird dabei einfach durch eine Variable ersetzt, die sich die Position merkt, an der das gefundene Element steht. Das sieht dann für das obige Beispiel so aus:

int[] werte = new int[] { 4, 2, 7, 3, 5, 1, 8 };

int found = -1;
for (int i = 0; i < werte.length; i++) {
  if (werte[i] > 5) {
    found = i;
    break;
  }
}
if (found >= 0) {
  System.out.println("Mindestens ein Wert ist größer als 5.");
  System.out.println("Einer davon steht an Position " + found + ".");
}

Wie wir sehen, dass die Variable
found mit -1 initialisiert wird. Das ist hier das equivalent zu false für den Fall, dass kein Element in dem Array die Bedingung erfüllt. Da in Java, C++ und vielen anderen Sprachen alle Arrays mit dem Element 0 beginnen, ist -1 ein guter Wert, von dem weiß, dass diese Position im Array nicht vorkommt. Mit if (found >= 0) prüft man später also einfach ob die Variable found eine gültige Position im Array definiert und weiß dadurch gleich ob und welches Element in einem Array die Bedingung erfüllt.

Hier das ganze auch nochmal als allgemeines Pattern:

int found = -1;
for (int i = 0; i < array.length; i++) {
  if (/* Bedingung prüfen */) {
    /* Aktion für Elemente ausführen, die Bedingung erfüllen */
    found = i;
    break; // Falls keine Aktion durchgeführt werden soll
    // und man nur an den ersten passenden Element interessiert ist.
  }
}
if (found >= 0) {
  // Aktion ausführen falls ein Element die Bedingung erfüllt
}

Jetzt sollten wir uns nochmal kurz über den Fall Gedanken machen, dass mehrere Elemente in dem Array die Bedingung erfüllen. Ist man nur an irgendeinem passenden Element interessiert, und möchte keine Aktion für alle passenden Elemente durchführen, kann man die Schleife einfach mit break beenden, sobald man ein Element gefunden und sich dessen Position gemerkt hat. In dem Fall wird found am Ende die Position des ersten passenden Elements beinhalten. Lässt man aber das break weg, weil man z.B. eine Aktion für alle passenden Elemente durchführen möchte, dann wird found am Ende die Position des letzten passenden Elements beinhalten.

Samstag, 29. März 2014

All- und Any-Pattern

Gerade als Programmieranfänger muss man häufig noch über Aufgaben nachdenken, die für fortgeschrittene Programmierer schon selbstverständlich sind. Hier möchte ich nun ein paar Muster vorstellen, die immer wieder auftauchen und bei denen man sich das nachdenken sparen kann.

Ist es z.B. erforderlich zu prüfen, ob in einem Array ein Element vorkommt, dass eine bestimmte Bedingung erfüllt so, kann man das mit dem Any-Pattern testen. ich schreibe das jetzt mal in Java Syntax, obwohl es genauso gut auch für jede andere Programmiersprache funktioniert, die Arrays unterstützt. Hier ein Beispiel, bei dem festgestellt werden soll, ob ein Array eine Zahl enthält, die größer als 5 ist.

int[] werte = new int[] { 4, 2, 7, 3, 5, 1, 8 };

boolean erfuellt = false;
for (int i = 0; i < werte.length; i++) {
  if (werte[i] > 5) {
    erfuellt = true;
    break;
  }
}
if (erfuellt) {
  System.out.println("Mindestens ein Wert ist größer als 5.");
}

Hieraus lässt sich ein Muster ableiten, dass immer funktioniert, wenn man eine derartige Aufgabe vor sich hat. Man beginnt damit eine boolesche Variable auf false zu setzen. Durchläuft dann das gesamte Array und prüft jedes Mal die Bedingung, die einen interessiert. In diesem Fall, ob der Wert größer als 5 ist. Ist diese Bedingung erfüllt wird die boolesche Variable auf true gesetzt, ansonsten nicht verändert. (Das ist wichtig.) Nach Durchlaufen der Schleife kann man einfach die boolesche Variable abfragen und dann etwas tun, was für den Fall passieren soll, falls wenigstens ein Element in dem Array die Bedingung erfüllt.

Gelegentlich kann es auch vorkommen, dass man mit allen gefunden Elementen etwas tun will, dass kann man dann natürlich in dem if-Block tun. Dann sollte man allerdings auf das break verzichten, da die Aktion sonst nur für das erste gefundene Elemente ausgeführt wird.

Hier nochmal als Muster:

boolean erfuellt = false;
for (/* for-Schleife über das gesamte Array */) {
  if (/* Bedingung prüfen */) {
    /* Aktion für Elemente ausführen, die Bedingung erfüllen */
    erfuellt = true;
    break; // Falls keine Aktion durchgeführt werden soll.
  }
}
if (erfuellt) {
  // Aktion ausführen falls ein Element die Bedingung erfüllt
}

Das gleiche gibt es auch noch für den Fall, dass alle Elemente in dem Array eine Bedingung erfüllen sollen:

boolean alle = true;
for (/* for-Schleife über das gesamte Array */) {
  if (/* Bedingung prüfen */) {
    // Aktion für Elemente ausführen, die Bedingung erfüllen
  } else {
    alle = false;
    break// Falls keine Aktion durchgeführt werden soll.
  }
}
if (alle) {
  // Aktion ausführen falls alle Elemente die Bedingung erfüllen
}

Hier wird die boolesche Variable zuerst mit true initialisiert und für den Fall, dass ein Element die Bedingung nicht erfüllt auf false gesetzt.