From 4b1a9203c547c019fc5398082ae19a3f3d4c3efe Mon Sep 17 00:00:00 2001 From: Peter Bengtsson Date: Tue, 8 Dec 2020 14:41:15 -0500 Subject: initial commit --- .../global_objects/array/reduce/index.html | 564 +++++++++++++++++++++ 1 file changed, 564 insertions(+) create mode 100644 files/de/web/javascript/reference/global_objects/array/reduce/index.html (limited to 'files/de/web/javascript/reference/global_objects/array/reduce') diff --git a/files/de/web/javascript/reference/global_objects/array/reduce/index.html b/files/de/web/javascript/reference/global_objects/array/reduce/index.html new file mode 100644 index 0000000000..bbb3e4d57c --- /dev/null +++ b/files/de/web/javascript/reference/global_objects/array/reduce/index.html @@ -0,0 +1,564 @@ +--- +title: Array.prototype.reduce() +slug: Web/JavaScript/Reference/Global_Objects/Array/Reduce +tags: + - Array + - ECMAScript 5 + - JavaScript + - Method + - Prototype + - Reduce + - Reference +translation_of: Web/JavaScript/Reference/Global_Objects/Array/Reduce +--- +
{{JSRef}}
+ +

Die reduce()-Methode reduziert ein Array auf einen einzigen Wert, indem es jeweils zwei Elemente (von links nach rechts) durch eine gegebene Funktion reduziert.

+ +
{{EmbedInteractiveExample("pages/js/array-reduce.html")}}
+ + + +

Syntax

+ +
arr.reduce(callback[, initialValue])
+ +

Parameter

+ +
+
callback
+
Funktion, welche auf jeden Wert im Array angewandet wird und vier Argumente hat: +
+
accumulator
+
Der kumulierte Wert ist der Rückgabewert von callback; der in der zuvor zurückgegebene Wert des letzten Aufrufes von callback oder initialValue werden verwendet.
+
currentValue
+
Das aktuell zu verarbeitende Element des Arrays.
+
currentIndex{{optional_inline}}
+
Der Index des aktuellen Elements des Arrays. Beginnt mit dem Index 0, falls initialValue angegeben wurde, ansonsten mit Index 1.
+
array{{optional_inline}}
+
Das Array, auf dem reduce abgerufen wird.
+
+
+
initialValue{{optional_inline}}
+
Der Wert des ersten Arguments, der bei dem ersten Aufruf in callback zu benutzt wird. Wenn kein Initialwert angegeben wird, wird das erste Element des Arrays benutzt. Das Aufrufen von reduce() auf einem leeren Array ohne Initialwerts führt zu einem Fehler.
+
+ +

Rückgabewert

+ +

Der Ergebniswert der Reduzierung.

+ +

Beschreibung

+ +

reduce() führt die callback-Funktion für jedes existierende Element in dem Array aus, Ausnahme sind nicht gesetzte Werte. callback hat vier Parameter:

+ + + +

Beim ersten Aufruf von callback sind die Werte von accumulator und currentValue in Abhängigkeit vom Parameter initialValue wie folgt:

+ + + +
+

Hinweis: Wenn initialValue nicht angegeben wird, wird reduce() die callback-Funktion startend beim Index 1 aufrufen, der erste Index wird übersprungen. Wenn initialValue angegeben ist, wird bei Index 0 begonnen.

+
+ +

Wenn das Array leer ist und kein initialValue angegeben ist, wird ein {{jsxref("TypeError")}} erzeugt. Wenn das Array nur ein Element hat (die Position ist egal) und kein initialValue angegeben ist oder wenn initialValue angegeben ist und das Array leer ist, wird der einzelne Wert sofort zurückgegeben, ohne callback aufzurufen.

+ +

Es ist immer sicherer initialValue anzugeben, weil es drei mögliche Ergebnisse ohne initialValue gibt, wie es im folgenden Beispiel gezeigt ist.

+ +
var maxCallback = ( acc, cur ) => Math.max( acc.x, cur.x );
+var maxCallback2 = ( max, cur ) => Math.max( max, cur );
+
+// reduce() without initialValue
+[ { x: 22 }, { x: 42 } ].reduce( maxCallback ); // 42
+[ { x: 22 }            ].reduce( maxCallback ); // { x: 22 }
+[                      ].reduce( maxCallback ); // TypeError
+
+// map/reduce; better solution, also works for empty or larger arrays
+[ { x: 22 }, { x: 42 } ].map( el => el.x )
+                        .reduce( maxCallback2, -Infinity );
+
+ +

Wie reduce() funktioniert

+ +

Angenommen die folgende reduce() Funktion wird genutzt:

+ +
[0, 1, 2, 3, 4].reduce(function (accumulator, currentValue, currentIndex, array) {
+  return accumulator + currentValue;
+});
+
+ +

Die callback-Funktion wird viermal aufgerufen, mit den Parametern und Rückgabewert für jeden Aufruf wir folgend beschrieben:

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
callbackaccumulatorcurrentValuecurrentIndexarrayRückgabewert
1. Aufruf011[0, 1, 2, 3, 4]1
2. Aufruf122[0, 1, 2, 3, 4]3
3. Aufruf333[0, 1, 2, 3, 4]6
4. Aufruf644[0, 1, 2, 3, 4]10
+ +

Der zurückgegebene Wert von reduce() ist der Rückgabewert der letzten callback-Funktion (10).

+ +

Es ist zusätzlich möglich eine {{jsxref("Functions/Arrow_functions", "Arrow-Funktion","",1)}} statt einer ganzen Funktion zu benutzen. Der folgende Quelltext erzeugt die gleiche Ausgabe wie der Vorherige:

+ +
[0, 1, 2, 3, 4].reduce( (prev, curr) => prev + curr );
+
+ +

Wenn als zweiter Parameter von reduce() initialValue angegeben ist, wird das Ergebnis wie folgt aussehen:

+ +
[0, 1, 2, 3, 4].reduce((accumulator, currentValue, currentIndex, array) => {
+  return accumulator + currentValue;
+}, 10);
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
callbackaccumulatorcurrentValuecurrentIndexarrayRückgabewert
1. Aufruf1000[0, 1, 2, 3, 4]10
2. Aufruf1011[0, 1, 2, 3, 4]11
3. Aufruf1122[0, 1, 2, 3, 4]13
4. Aufruf1333[0, 1, 2, 3, 4]16
5. Aufruf1644[0, 1, 2, 3, 4]20
+ +

Der von reduce() zurückgegebene Wert ist in diesem Fall 20.

+ +

Beispiele

+ +

Alle Elemente eines Arrays summieren

+ +
var sum = [0, 1, 2, 3].reduce(function (accumulator, currentValue) {
+  return accumulator + currentValue;
+}, 0);
+// sum is 6
+
+ +

Alternativ als Arrow-Funktion geschrieben:

+ +
var total = [ 0, 1, 2, 3 ].reduce(
+  ( accumulator, currentValue ) => accumulator + currentValue,
+  0
+);
+ +

Summe von Werten in einem Objektarray

+ +

Um in einem Array von Objekten Werte aufzusummieren, muss ein Initialwert angegeben werden, so dass jedes Element in der Funktion durchlaufen wird.

+ +
var initialValue = 0;
+var sum = [{x: 1}, {x:2}, {x:3}].reduce(function (accumulator, currentValue) {
+    return accumulator + currentValue.x;
+},initialValue)
+
+console.log(sum) // logs 6
+
+ +

Alternativ als Arrow-Funktion geschrieben:

+ +
var initialValue = 0;
+var sum = [{x: 1}, {x:2}, {x:3}].reduce(
+    (accumulator, currentValue) => accumulator + currentValue.x
+    ,initialValue
+);
+
+console.log(sum) // logs 6
+ +

Geschachtelte Arrays zu einem flachen Array machen

+ +
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(
+  function(accumulator, currentValue) {
+    return accumulator.concat(currentValue);
+  },
+  []
+);
+// flattened is [0, 1, 2, 3, 4, 5]
+
+ +

Alternativ als Arrow-Funktion geschrieben:

+ +
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(
+  ( accumulator, currentValue ) => accumulator.concat(currentValue),
+  []
+);
+
+ +

Zählen von Instanzen eines Wertes in einem Objekt

+ +
var names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
+
+var countedNames = names.reduce(function (allNames, name) {
+  if (name in allNames) {
+    allNames[name]++;
+  }
+  else {
+    allNames[name] = 1;
+  }
+  return allNames;
+}, {});
+// countedNames is:
+// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }
+
+ +

Objekte nach einer Eigenschaft gruppieren

+ +
var people = [
+  { name: 'Alice', age: 21 },
+  { name: 'Max', age: 20 },
+  { name: 'Jane', age: 20 }
+];
+
+function groupBy(objectArray, property) {
+  return objectArray.reduce(function (acc, obj) {
+    var key = obj[property];
+    if(!acc[key]) {
+      acc[key] = [];
+    }
+    acc[key].push(obj);
+    return acc;
+  }, {});
+}
+
+var groupedPeople = groupBy(people, 'age');
+// groupedPeople is:
+// {
+//   20: [
+//     { name: 'Max', age: 20 },
+//     { name: 'Jane', age: 20 }
+//   ],
+//   21: [{ name: 'Alice', age:21 }]
+// }
+
+ +

Verbinden von Arrays in einem Array von Objekten mithilfe des Spread-Operators und von initialValue

+ +
// friends - an array of objects
+// where object field "books" - list of favorite books
+var friends = [{
+  name: 'Anna',
+  books: ['Bible', 'Harry Potter'],
+  age: 21
+}, {
+  name: 'Bob',
+  books: ['War and peace', 'Romeo and Juliet'],
+  age: 26
+}, {
+  name: 'Alice',
+  books: ['The Lord of the Rings', 'The Shining'],
+  age: 18
+}];
+
+// allbooks - list which will contain all friends' books +
+// additional list contained in initialValue
+var allbooks = friends.reduce(function(accumulator, currentValue) {
+  return [...accumulator, ...currentValue.books];
+}, ['Alphabet']);
+
+// allbooks = [
+//   'Alphabet', 'Bible', 'Harry Potter', 'War and peace',
+//   'Romeo and Juliet', 'The Lord of the Rings',
+//   'The Shining'
+// ]
+ +

Duplikate in einem Array entfernen

+ +
let arr = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];
+let result = arr.sort().reduce((accumulator, current) => {
+    const length = accumulator.length;
+    if (length === 0 || accumulator[length - 1] !== current) {
+        accumulator.push(current);
+    }
+    return accumulator;
+}, []);
+console.log(result); //[1,2,3,4,5]
+
+ +

Sequenzielle Abarbeitung von Promises

+ +
/**
+ * Runs promises from array of functions that can return promises
+ * in chained manner
+ *
+ * @param {array} arr - promise arr
+ * @return {Object} promise object
+ */
+function runPromiseInSequence(arr, input) {
+  return arr.reduce(
+    (promiseChain, currentFunction) => promiseChain.then(currentFunction),
+    Promise.resolve(input)
+  );
+}
+
+// promise function 1
+function p1(a) {
+  return new Promise((resolve, reject) => {
+    resolve(a * 5);
+  });
+}
+
+// promise function 2
+function p2(a) {
+  return new Promise((resolve, reject) => {
+    resolve(a * 2);
+  });
+}
+
+// function 3 - will wrapped in a resolved promise by .then()
+function f3(a) {
+  return a * 3;
+}
+
+// promise function 4
+function p4(a) {
+  return new Promise((resolve, reject) => {
+    resolve(a * 4);
+  });
+}
+
+const promiseArr = [p1, p2, f3, p4];
+runPromiseInSequence(promiseArr, 10)
+  .then(console.log);    // 1200
+
+ +

Funktionskomposition ermöglicht Pipelining

+ +
// Building-blocks to use for composition
+const double = x => x + x;
+const triple = x => 3 * x;
+const quadruple = x => 4 * x;
+
+// Function composition enabling pipe functionality
+const pipe = (...functions) => input => functions.reduce(
+    (acc, fn) => fn(acc),
+    input
+);
+
+// Composed functions for multiplication of specific values
+const multiply6 = pipe(double, triple);
+const multiply9 = pipe(triple, triple);
+const multiply16 = pipe(quadruple, quadruple);
+const multiply24 = pipe(double, triple, quadruple);
+
+// Usage
+multiply6(6); // 36
+multiply9(9); // 81
+multiply16(16); // 256
+multiply24(10); // 240
+
+ +

Mapfunktion mit reduce

+ +
if (!Array.prototype.map) {
+  Array.prototype.map = function(callback, thisArg) {
+    return this.reduce(function(mappedArray, currentValue, index, array) {
+      mappedArray[index] = callback.call(thisArg, currentValue, index, array);
+      return mappedArray;
+    }, []);
+  };
+}
+
+[1, 2, , 3].map(
+  (currentValue, index, array) => currentValue + index + array.length
+); // [5, 7, , 10]
+
+
+ +

Polyfill

+ +
// Production steps of ECMA-262, Edition 5, 15.4.4.21
+// Reference: http://es5.github.io/#x15.4.4.21
+// https://tc39.github.io/ecma262/#sec-array.prototype.reduce
+if (!Array.prototype.reduce) {
+  Object.defineProperty(Array.prototype, 'reduce', {
+    value: function(callback /*, initialValue*/) {
+      if (this === null) {
+        throw new TypeError( 'Array.prototype.reduce ' +
+          'called on null or undefined' );
+      }
+      if (typeof callback !== 'function') {
+        throw new TypeError( callback +
+          ' is not a function');
+      }
+
+      // 1. Let O be ? ToObject(this value).
+      var o = Object(this);
+
+      // 2. Let len be ? ToLength(? Get(O, "length")).
+      var len = o.length >>> 0;
+
+      // Steps 3, 4, 5, 6, 7
+      var k = 0;
+      var value;
+
+      if (arguments.length >= 2) {
+        value = arguments[1];
+      } else {
+        while (k < len && !(k in o)) {
+          k++;
+        }
+
+        // 3. If len is 0 and initialValue is not present,
+        //    throw a TypeError exception.
+        if (k >= len) {
+          throw new TypeError( 'Reduce of empty array ' +
+            'with no initial value' );
+        }
+        value = o[k++];
+      }
+
+      // 8. Repeat, while k < len
+      while (k < len) {
+        // a. Let Pk be ! ToString(k).
+        // b. Let kPresent be ? HasProperty(O, Pk).
+        // c. If kPresent is true, then
+        //    i.  Let kValue be ? Get(O, Pk).
+        //    ii. Let accumulator be ? Call(
+        //          callbackfn, undefined,
+        //          « accumulator, kValue, k, O »).
+        if (k in o) {
+          value = callback(value, o[k], k, o);
+        }
+
+        // d. Increase k by 1.
+        k++;
+      }
+
+      // 9. Return accumulator.
+      return value;
+    }
+  });
+}
+
+ +

Wenn es wirklich notwendig ist veraltete JavaScript-Umgebungen zu benutzen, die Object.defineProperty() nicht unterstützen, ist es besser Array.prototype nicht komplett zu ersetzen, weil man es nicht non-enumerable machen kann.

+ +

Spezifikationen

+ + + + + + + + + + + + + + + + + + + + + + + + +
SpezificationStatusKommentar
{{SpecName('ES5.1', '#sec-15.4.4.21', 'Array.prototype.reduce()')}}{{Spec2('ES5.1')}}Initiale Definition. Implementiert in JavaScript 1.8.
{{SpecName('ES6', '#sec-array.prototype.reduce', 'Array.prototype.reduce()')}}{{Spec2('ES6')}}
{{SpecName('ESDraft', '#sec-array.prototype.reduce', 'Array.prototype.reduce()')}}{{Spec2('ESDraft')}}
+ +

Browserkompatibilität

+ +
+ + +

{{Compat("javascript.builtins.Array.reduce")}}

+
+ +

Siehe auch

+ + -- cgit v1.2.3-54-g00ecf