Home
Über mich
Veröffentlichungen

XML XML-Schema XPath XSL-T XSL-FO XQuery XProc SVG

XPath / XPath-Funktionen / XPath: Sequenz-Funktionen / XPath: fold-left

XPath: fold-left

XPath: fold-left

➪ Die XPath-Funktion fold-left verarbeitet alle Items einer Sequenz von links nach rechts. Sie eignet sich damit gut für erweiterte Zahlenfunktionen, etwa bei Kumulierungen oder Multiplikationen.

Auf dieser Seite:

Siehe auch fold-right.

Sequenzen multiplizieren

Während die sum-Funktion Zahlenwerte addieren kann, gibt es kein Standardverfahren für die Multiplikation. Hier kann fold-left gute Hilfe bieten. Der folgende Aufruf multipliziert alle Werte von 1 bis 5.


let $input := (1 to 5)
return element {'ergebnis'}{ 
    fold-left( 
               $input, 
               1, 
               function($a, $b){
                  $a * $b                        
               }
    )        
}

Das Ergebnis ist unschwer nachvollziehbar:


<ergebnis>120</ergebnis>

Sie haben auch Null-Werte in der Sequenz und möchten diese ignorieren? Kein Problem:


let $input := (1 to 5, 0)
return element {'ergebnis'}{ 
    fold-left( 
               $input[. != 0], 
               1, 
               function($a, $b){
                  $a * $b                        
               }
    )        
}

Sequenzen kumulieren

Ähnlich wie viele andere Zahlenfunktionen (sum, count, avg u.a.m) liefert die soeben beschriebene Multiplikation nur einen Einzelwert zurück. Wenn Sie jedoch die Zwischenwerte ebenfalls benötigen, etwa bei Kumulierungen, können Sie so vorgehen:


element {'ergebnis'}{ 
    for $w in (1 to 10) return element {'value'}{
        attribute {'i'}{$w},
        attribute {'kumuliert'}{
            fold-left(
                   (  1 to (xs:int($w))  ), 
                   0, 
                   function($a, $b){
                        $a + $b                        
                    }
              )
        },
        attribute {'multipliziert'}{
            fold-left(
                   (  1 to (xs:int($w))  ), 
                   1, 
                   function($a, $b){
                        $a * $b                        
                    }
              )
        }
    }    
 }

Im vorliegenden Fall können Sie analog mit fold-right arbeiten: Das Resultat ist unverändert:


<ergebnis>
   <value i="1"  kumuliert="1"  multipliziert="1"/>
   <value i="2"  kumuliert="3"  multipliziert="2"/>
   <value i="3"  kumuliert="6"  multipliziert="6"/>
   <value i="4"  kumuliert="10" multipliziert="24"/>
   <value i="5"  kumuliert="15" multipliziert="120"/>
   <value i="6"  kumuliert="21" multipliziert="720"/>
   <value i="7"  kumuliert="28" multipliziert="5040"/>
   <value i="8"  kumuliert="36" multipliziert="40320"/>
   <value i="9"  kumuliert="45" multipliziert="362880"/>
   <value i="10" kumuliert="55" multipliziert="3628800"/>
</ergebnis

Siehe auch for-each und xsl:call-template.

fold-left

Die XPath-Funktion fold-left fordert drei Parameter ein: zwei Sequenzen sowie eine Funktion, mit der das Ergebnis berechnet wird. Der folgende Aufruf definiert zwei Sequenzen sowie deren Verkettung (Komma!) in einer Funktion.


<xsl:template match="/">
  <root>
   <xsl:for-each 
        select="fn:fold-left(
                   (5 to 10), 
                   (15 to 20), 
                   function($a, $b){$a, $b})">
    <wert>
     <xsl:value-of select="."/>
    </wert>
   </xsl:for-each>
  </root>
</xsl:template>

Bemerkenswert ist hierbei, dass die zweite Sequenz zuerst betrachtet wird:


<root>
  <wert>15</wert>
  <wert>16</wert>
  <wert>17</wert>
  <wert>18</wert>
  <wert>19</wert>
  <wert>20</wert>
  <wert>5</wert>
  <wert>6</wert>
  <wert>7</wert>
  <wert>8</wert>
  <wert>9</wert>
  <wert>10</wert>
</root>

Das zweite Beispiel multipliziert die Einzelwerte der Reihe 6 * 1 * 2 * 3 miteinander:


<xsl:template match="/">
  <root>
   <xsl:for-each 
        select="fn:fold-left(
                   (1 to 3), 
                   6, 
                   function($a, $b){$a * $b})">
    <wert>
     <xsl:value-of select="."/>
    </wert>
   </xsl:for-each>
  </root>
</xsl:template>

... und kommt auf ein nachvollziehbares Ergebnis:


<root>
  <wert>36</wert>
</root>

Auch andere bewährte Funktionen können eingebunden werden, etwa concat:


<xsl:template match="/">
  <root>
   <xsl:for-each 
        select="fn:fold-left(
                   1 to 5, 
                   'Sprachlos', 
                   fn:concat(?, ' | ', ?))">
    <wert>
     <xsl:value-of select="."/>
    </wert>
   </xsl:for-each>
  </root>
</xsl:template>

Das erzielte Ergebnis sieht dann so aus:


<root>
  <wert>Sprachlos | 1 | 2 | 3 | 4 | 5</wert>
</root>

wg / 1. Mai 2019



Fragen? Anmerkungen? Tipps?

Bitte nehmen Sie Kontakt zu mir auf.






Vielen Dank für Ihr Interesse an meiner Arbeit.



V.i.S.d.P.: Wilfried Grupe * Klus 6 * 37643 Negenborn

☎ 0151. 750 360 61 * eMail: info10@wilfried-grupe.de

www.wilfried-grupe.de/foldleft.html