Startseite
jump to top

Startseite / Vorlagenentwicklung / Vorlagensyntax / Ausdrücke / Abbildungs-Ausdrücke

Abbildungs-Ausdrücke (Lambda)Verfügbar ab FirstSpirit-Version 4.1

Bei einem Abbildungs-Ausdruck (auch "Lambda-Ausdruck") handelt es sich um eine anonyme Funktion, die Ausdrücke und Anweisungen enthält. Er wird in FirstSpirit mit dem Operator -> ("Lambda", Pfeil bestehend aus einem Minus- und einem direkt folgenden Größer-Zeichen) dargestellt. Dieser bedeutet so viel wie "wechselt zu" oder "bildet ... ab auf".

Auf der linken Seite des Operators Lambda wird ein Eingabeparameter angegeben, der frei gewählt werden kann. Dabei handelt es sich um einen so genannten "anonymen" Eingabeparameter, der quasi ein Platzhalter für ein Objekt (z.B. eine Menge von Werten, in FirstSpirit: Listen) ist. Auf den Wert kann nur innerhalb der Interpretation zugegriffen werden und ist daher nur während der Ausführung von Interesse.

Auf der rechten Seite befindet sich ein Ausdruck oder Anweisungsblock.

Beispiel:

Der Lambda-Ausdruck

x -> x * x 

bedeutet

"x wird x Mal mit sich selbst multipliziert"

Auf der rechten Seite können je nach Einsatzfall verschiedene Methoden angewendet werden:

1 .Beispiel: Sortierung mit der Methode "sort(Lambda)"

Haben Listen oder Maps mehrere Attribute pro Element (vergleichbar einem Datensatz mit mehreren Spalten), können die Elemente mit Lambda (->) nach den einzelnen Attributen sortiert werden.

Im folgenden Beispiel wird über $CMS_SET(...)$ eine Liste von Schlüssel-Wert-Paaren ("Map") erzeugt. Jede Map enthält pro Element einen Namen ("name") und ein Login ("login"):

$CMS_SET(_members, [
{
"name" : "Max Mustermann",
"login" : "mustermann"
}, {
"name" : "Tina Testuser",
"login" : "testuser"
}, {
"name" : "Maxine Musterfrau",
"login" : "musterfrau"
}
])$

Die Elemente dieser Liste können nun mithilfe einer $CMS_FOR(...)$-Schleife und der Methode sort nach dem Schlüssel "login" aufsteigend sortiert ausgegeben werden:

$CMS_FOR(_member, _members.sort(x -> x["login"]))$
$CMS_VALUE(_member["name"] + " (" + _member["login"] + ")")$<br />
$CMS_END_FOR$

Zunächst wird die Liste (_members) mithilfe der sort-Funktion anhand des Schlüssels "login" alphabetisch aufsteigend sortiert. Dazu wird mit dem Lambda-Ausdruck nicht das Element selbst (jeweils eine Map), sondern der Wert des Schlüssels "login" (aus der Map) für die Sortierung berücksichtigt. Mit der $CMS_FOR(...)$-Schleife wird dann über die sortierte Liste iteriert und über den $CMS_VALUE(...)$-Ausdruck Name und Login in runden Klammern zurückgegeben.

Die Ausgabe sieht folgendermaßen aus:

Maxine Musterfrau (musterfrau)
Max Mustermann (mustermann)
Tina Testuser (testuser)

Eine weitere Möglichkeit, Listen mithilfe des Lambda-Ausdrucks anhand mehrerer Kriterien zu sortieren, ist folgende:

Diese Liste von Maps enthält z.B. Namen, die sich aus Vor- und Nachnamen zusammensetzen:

$CMS_SET(_members, [
{
"name" : "Redakteur",
"cname" : "Rudi"
}, {
"name" : "Mustermann",
"cname" : "Sven"
}, {
"name": "Testbenutzer",
"cname" : "Anne"
}, {
"name" : "Mustermann",
"cname" : "Stefan"
}
])$

Mit folgender Anweisung können die Namen nach Nachnamen und dann nach dem Vornamen in alphabetisch aufsteigender Sortierung ausgegeben werden. Nach- und Vorname werden dabei durch ein Komma getrennt.

$CMS_FOR(_member, _members.sort(x -> x.cname).sort(x -> x.name))$
$CMS_VALUE(#for.index + 1)$. $CMS_VALUE(_member.name)$, $CMS_VALUE(_member.cname)$
$CMS_END_FOR$

Die Namen werden in dieser Reihenfolge ausgegeben:

  1. Mustermann, Stefan
  2. Mustermann, Sven
  3. Redakteur, Rudi
  4. Testbenutzer, Anne

3. Beispiel: Filterung mit den Methoden "max(Lambda)" und "min(Lambda)"

Im folgenden Beispiel wird ebenfalls eine Liste von Maps erzeugt, und zwar zu Immobilien mit verschiedenen Informationen wie Adresse, Preis und Größe:

$CMS_SET(immos, [
{"Name":"A", "Adresse":{"Ort":"Dortmund", "PLZ":42400, "Strasse":"Amsterdamer Platz", "Nr":"32"}, "Preis":177000, "qmWohn":190},
{"Name":"B", "Adresse":{"Ort":"Bochum", "PLZ":44877, "Strasse":"Allestr.", "Nr":"114"}, "Preis":150000, "qmWohn":150},
{"Name":"C", "Adresse":{"Ort":"Hagen", "PLZ":42345, "Strasse":"Kleiner Weg", "Nr":"2b"}, "Preis":555000, "qmWohn":320},
{"Name":"D", "Adresse":{"Ort":"Bochum", "PLZ":44890, "Strasse":"Zeppelindamm", "Nr":"93"}, "Preis":352000, "qmWohn":210}
])$

Über die Methoden max und min können die teuerste bzw. die günstigste Immobilie ausgegeben werden:

Teuerste Immobilie:  
$CMS_VALUE(immos.max(x -> x.Preis))$<br>
Günstigste Immobilie:
$CMS_VALUE(immos.min(x -> x.Preis))$<br>

Ausgabe:

Teuerste Immobilie: {Adresse={Nr=2b, Ort=Hagen, PLZ=42345, Strasse=Kleiner Weg}, Name=C, Preis=555000, qmWohn=320}
Günstigste Immobilie: {Adresse={Nr=114, Ort=Bochum, PLZ=44877, Strasse=Allestr.}, Name=B, Preis=150000, qmWohn=150}

4. Beispiel: Filterung von Elementen mit der Methode "filter(Lambda)"

Aus der oben definierten Liste können über die Methode filter Immobilien ausgegeben werden, deren Preis einen bestimmten Wert übersteigt (hier: > 200000):

$CMS_FOR(_immobilie, _immobilien.filter(x -> x.Preis > 200000))$
$CMS_VALUE(_immobilie.Preis)$ ($CMS_VALUE(_immobilie.Name)$)<br/>
$CMS_END_FOR$

Auf diese Weise werden die Immobilien, deren Wert 200000 übersteigt, mit Preis und Name ausgegeben:

555000 (C)
352000 (D)

5. Beispiel: Ausgabe von Listenelementen in einer Sammlung mit der Methode "map(Lambda)"

Aus der oben definierten Liste können über die Methode sort alle Preise der Immobilien aufsteigend sortiert werden und über die Methode map als Sammlung ausgegeben werden:

Sortierte Immobilien-Preise:  
$CMS_VALUE(immos.map(x -> x.Preis)).sort())$<br>

Ausgabe:

Sortierte Immobilien-Preise: [150000, 177000, 352000, 555000]

6. Beispiel: Filtern von Duplikaten mit der Methode "filter(Lambda)"

Sollen aus einer Liste mit Schlüssel-Wert-Paaren Duplikate bei der Ausgabe herausgefiltert werden, kann dies ebenfalls über die Methode filter erfolgen.

Wird die oben definierte Liste um Immobilien mit Postleitzahlen ergänzt, die bereits vorhanden sind, z.B.

$CMS_SET(immos, [
{"Name":"A", "Adresse":{"Ort":"Dortmund", "PLZ":42400, "Strasse":"Amsterdamer Platz", "Nr":"32"}, "Preis":177000, "qmWohn":190},
{"Name":"A2", "Adresse":{"Ort":"Dortmund", "PLZ":42400, "Strasse":"Amsterdamer Weg", "Nr":"3"}, "Preis":153000, "qmWohn":100},
{"Name":"B", "Adresse":{"Ort":"Bochum", "PLZ":44877, "Strasse":"Alleestr.", "Nr":"114"}, "Preis":150000, "qmWohn":150},
{"Name":"B2", "Adresse":{"Ort":"Bochum", "PLZ":42400, "Strasse":"Barcelonaweg", "Nr":"3"}, "Preis":203000, "qmWohn":140},
{"Name":"C", "Adresse":{"Ort":"Hagen", "PLZ":42345, "Strasse":"Kleiner Weg", "Nr":"2b"}, "Preis":555000, "qmWohn":320},
{"Name":"C2", "Adresse":{"Ort":"Hagen", "PLZ":42345, "Strasse":"Großer Weg", "Nr":"22"}, "Preis":775000, "qmWohn":220},
{"Name":"D", "Adresse":{"Ort":"Bochum", "PLZ":44890, "Strasse":"Zeppelindamm", "Nr":"93"}, "Preis":352000, "qmWohn":210},
{"Name":"D2", "Adresse":{"Ort":"Bochum", "PLZ":44890, "Strasse":"Zeppelinweg", "Nr":"39"}, "Preis":552000, "qmWohn":110}
])$

können über die Anweisung

$CMS_VALUE(immos.map(x -> x.Adresse.PLZ).filter(x -> x > 42000 && x < 43000).iterator.toSet)$

bzw.

$CMS_SET(_value, {})$
$CMS_SET(_void, _value.addAll(immos.map(x -> x.Adresse.PLZ).filter(x -> x > 42000 && x < 43000)))$
$CMS_VALUE(_value)$

alle Postzahlen im Bereich von 42000 bis 43000 ohne Duplikate zurückgeliefert werden, für die eine Immobilie erfasst wurde.

Ausgabe:

[42345, 42400]

7. Beispiel: Ausgabe einer Liste eindeutiger Elemente mit der Methode "distinct(Lambda)"

Über die Methode distinct werden Duplikate einer Liste entsprechend einer Bedingung eliminiert bzw. ignoriert. Diese Methode kann z.B. für Glossare oder Übersichten verwendet werden, die dann beispielsweise verlinkt auch als Navigationselement dienen können.

Beispiel Glossar / Index

Um aus einer Liste mit Vornamen einen Index der Anfangsbuchstaben zu erstellen, kann auf die Liste

$CMS_SET(_names, ["Birgit", "Andreas", "Barbara", "Emma", "Anne", "Celine"])$

folgende Anweisung ausgeführt werden:

$CMS_FOR(_name, _names.distinct(x -> x.charAt(0)).sort)$
$CMS_IF(!#for.isFirst)$ | $CMS_END_IF$
$CMS_VALUE(_name.charAt(0))$
$CMS_END_FOR$

In diesem Beispiel wird über die $CMS_FOR(...)$-Anweisung zunächst mithilfe der Methode distinct der jeweils erste Eintrag der Namensliste zu einem Anfangsbuchstaben (.charAt(0)) ermittelt, die Bedingung ist hier also der Anfangsbuchstabe. Das Ergebnis dabei ist:

Birgit, Andreas, Emma, Celine

Die ermittelten Elemente werden anschließend über sort sortiert (alphabetisch aufsteigend). Ergebnis:

Andreas, Birgit, Celine, Emma

Über die $CMS_VALUE(...)$-Anweisung wird dann der erste Buchstabe der Elemente ausgegeben, getrennt durch einen senkrechten Strich | :

A | B | C | E
Wichtig Die Einträge "Barbara" und "Anne" werden in diesem Beispiel ignoriert, da distinct immer nur das erste Vorkommen von Namen mit demselben Anfangsbuchstaben berücksichtigt. Würde die Namensliste erst alphabetisch geordnet (sort) und dann distinct angewendet, würden die Einträge "Birgit" und "Anne" ignoriert, da diese alphabetisch nach "Barbara" bzw. "Andreas" folgen.

Beispiel Übersicht

Im folgenden Beispiel wird aus einer Liste mit Immobilien eine Postleitzahlen-Übersicht erzeugt. Dabei gibt es zu einer Postleitzahl mehrere Immobilien. Ziel ist es somit, PLZ-Duplikate zu eliminieren, alle weiteren Immobilien-Informationen sind hier nicht von Bedeutung.

$CMS_SET(immos, [
{"Name":"A", "Adresse":{"Ort":"Dortmund", "PLZ":44400, "Strasse":"Amsterdamer Platz", "Nr":"32"}, "Preis":177.000, "qmWohn":190},
{"Name":"B", "Adresse":{"Ort":"Dortmund", "PLZ":44400, "Strasse":"Amsterdamer Weg", "Nr":"64"}, "Preis":180.000, "qmWohn":195},
{"Name":"C", "Adresse":{"Ort":"Dortmund", "PLZ":41877, "Strasse":"Alleestr.", "Nr":"114"}, "Preis":150.000, "qmWohn":150},
{"Name":"D", "Adresse":{"Ort":"Dortmund", "PLZ":41877, "Strasse":"Buchenweg", "Nr":"11"}, "Preis":115.000, "qmWohn":100},
{"Name":"E", "Adresse":{"Ort":"Bochum", "PLZ":42345, "Strasse":"Kleiner Weg", "Nr":"2b"}, "Preis":555.000, "qmWohn":320},
{"Name":"F", "Adresse":{"Ort":"Bochum", "PLZ":42345, "Strasse":"Hohe Straße", "Nr":"6"}, "Preis":55.000, "qmWohn":64},
{"Name":"G", "Adresse":{"Ort":"Bochum", "PLZ":42345, "Strasse":"Tiefer Weg", "Nr":"21"}, "Preis":38.000, "qmWohn":37}
])$

Über eine $CMS_FOR(...)$-Anweisung wird die Immobilien-Liste mithilfe der Methode sort zunächst nach Postleitzahl sortiert (aufsteigend). Anschließend werden mit der Methode distinct die jeweils ersten Einträge zu einer Postleitzahl ermittelt und über $CMS_VALUE(...)$ ausgegeben:

<h4>Übersicht unserer Immobilien nach Postleitzahl:</h4>
$CMS_FOR(_immo, immos.sort(x -> x.Adresse.PLZ).distinct(x -> x.Adresse.PLZ))$
* $CMS_VALUE(_immo.Adresse.PLZ)$<br />
$CMS_END_FOR$

Die Ausgabe lautet:

Übersicht unserer Immobilien nach Postleitzahl:
* 41877
* 42345
* 44400
Wichtig Auch in diesem Beispiel werden die Einträge zu den Immobilien "B", "D", "F" und "G" durch die Methode distinct ignoriert, da immer nur der erste Eintrag zu einer Postleitzahl berücksichtigt wird.

8. Beispiel: Summe einer Zahlenreihe (Σ-Summe) mit "fold(Lambda)"

Über Lambda kann auch die Summe einer Zahlenreihe ermittelt werden, z.B. die Summe der Zahlen von 1 bis 5:

1 + 2 + 3 + 4 + 5 = ?

Dazu wird die Methode fold verwendet, z.B.:

$CMS_VALUE([1..5].fold(s : 0, x -> s + x))$

Die anonyme Funktion fold verfügt über zwei Parameter:

  • Der erste Parameter legt den Eingabeparameter und seinen Startwert fest (im Beispiel "s : 0").
  • Beim zweiten Parameter handelt es sich um einen Lambda-Ausdruck, in dem s verwendet werden kann (im Beispiel "x -> s + x", wobei x der Eingabeparameter des Lambda-Ausdrucks ist, s + x der Ausdruck). Der Wert von s wird somit während der Interpretation fortwährend angepasst.

Am Schluß wird der Wert von s ausgegeben. x ist immer ein Wert aus der Wertemenge.

Im 1. Durchgang hat der Eingabeparameter der fold-Funktion s den Startwert (s=0) und der Eingabeparameter des Lambda-Ausdrucks x den Wert des ersten Elementes ("1"). Im Ausdruck wird somit der Wert von s um den Wert "1" erhöht, so dass der Wert von s "1" beträgt, kurz:

s=0,  x=1   =>   s = s + x   =   0 + 1   =   1

Im 2. Durchgang hat s den Wert "1" (s=2). x hat den Wert des zweiten Elementes ("2"). Der Wert von s beträgt nun "3":

s=1,  x=2   =>   s = s + x   =   1 + 2   =   3

Im 3. Durchgang hat s den Wert "3" (s=3). x hat den Wert des dritten Elementes ("3"). Der Wert von s beträgt nun "10":

s=3,  x=3   =>   s = s + x   =   3 + 3   =   6

Im 4. Durchgang hat s den Wert "6" (s=6). x hat den Wert des vierten Elementes ("4"). Der Wert von s beträgt nun "6":

s=6,  x=4   =>   s = s + x   =   6 + 4   =   10

Im 5. Durchgang hat s den Wert "10" (s=10). x hat den Wert des fünften Elementes ("5"). Der Wert von s beträgt nun "6":

s=10,  x=5   =>   s = s + x   =   10 + 5   =   15

Das Endergebnis ist damit 15.

9. Beispiel: Produkt einer Zahlenreihe (Π-Produkt) mit "fold(Lambda)"

Zur Berechnung von Produkten aus Zahlenreihen wird ebenfalls die Methode fold verwendet (siehe auch 6. Beispiel), z.B.:

$CMS_VALUE([1..4].fold(p : 1, x -> p*x))$

In diesem Beispiel wird das Produkt der Zahlen von 1 bis 4 ermittelt, also

1 * 2 * 3 * 4 = ?

p ist dabei Eingabeparameter und Startwert der fold-Funktion. Mit diesem Wert wird bei der Produktbildung begonnen.

Im 1. Durchgang hat der Eingabeparameter der fold-Funktion p den Startwert (p=1) und der Eingabeparameter des Lambda-Ausdrucks x den Wert des ersten Elementes ("1"). Im Ausdruck wird somit der Wert von p mit dem Wert "1" multipliziert, so dass der Wert von p "1" beträgt, kurz:

p=1,  x=1   =>   p = p * x   =   1 * 1   =   1

Im 2. Durchgang hat p den Wert "1" (p=1). x hat den Wert des zweiten Elementes ("2"). Der Wert von p beträgt nun "2":

p=1,  x=2   =>   p = p * x   =   1 * 2   =   2

Im 3. Durchgang hat p den Wert "2" (p=2). x hat den Wert des dritten Elementes ("3"). Der Wert von p beträgt nun "6":

p=2,  x=3   =>   p = p * x   =   2 * 3   =   6

Im 4. Durchgang hat p den Wert "6" (p=6). x hat den Wert des vierten Elementes ("4"). Der Wert von p beträgt nun "24":

p=6,  x=4   =>   p = p * x   =   6 * 4   =   24

Das Endergebnis ist damit 24.

© 2005 - 2020 e-Spirit AG | Alle Rechte vorbehalten. | FirstSpirit 2020-07 | Datenschutz | Impressum | Kontakt