我写过减少JavaScript的原生实现。但是我想看看我们是否可以使用此减少来实现ReduceRight。
Array.prototype.myReduce = function(cb, initialVal) {
if (!cb)
throw new Error("No CB defined");
let [accumulator, ...arr] = initialVal === undefined ? [...this] : [initialVal, ...this];
for (var i = 0; i < this.length; i++) {
accumulator = cb.call(undefined, accumulator, arr[i], i, arr);
}
return accumulator;
}
我从this article读到了
现在你可能会注意到一些事情。不是地图只是一个特例 降低?是!事实上,我们可以用reduce的堂兄来实现地图 reduceRight。 reduceRight就像reduce一样,除了它减少了 反向列出项目。所以,它会首先遇到Nil, 然后是倒数第二个项目,并继续前进,直到它到达第一个 列表中的项目。 reduceRight可以按如下方式实现:
我无法理解如何实施reduceRight(没有反转数组)
这是我的实施:
Array.prototype.myReduceRight2 = function(cb, initialVal) {
if (!cb)
throw new Error("No CB defined");
const arr = [...this].reverse(); //DONOT REVERSE! Looking for alternate solution(s)
const res = arr.myReduce((acc, val) => {
return acc.concat(val);
}, initialVal); // pass initialVal
return res;
}
答案 0 :(得分:3)
以下是我在个人图书馆中使用的reduceRight
的实现。
<强>代码:强>
Array.prototype.myReduceRight = function(callback, initialValue) {
var
/* Cache the length of the context. */
length = this.length >>> 0,
/* Create a counter defaulting at the index of the last element in the context. */
counter = length - 1;
/* Check whether a second argument has been given or not. */
if (arguments.length < 2) {
/* Repeat until the counter is less than or equal to the length of the
context or when the counter exists as an index in the context. */
while (counter >= 0 && !(counter in this)) {
/* Decrement the counter. */
counter--;
}
/* Set the inital value. */
initialValue = this[counter--];
}
/* Repeat until the counter is less than 0. */
while (counter >= 0) {
/* Check whether the counter exists as an index in the context. */
if (counter in this) {
/* Set the initial value to be the return value of the given callback. */
initialValue = callback.call(this, initialValue, this[counter], counter, this);
}
/* Decrement the counter. */
counter--;
}
/* Return the calculated value. */
return initialValue;
}
const array = [1, 2, 3, 4];
console.log(array.myReduceRight((acc, cur) => acc + cur));
答案 1 :(得分:2)
在函数式编程中,reduce
又名foldl
会像这样减少
foldl (fn, [head:tail], acc) = foldl (fn, tail, fn(acc, head))
和foldr
就是这个
foldr (fn, [head:tail], acc) = fn (head, foldr(fn, tail, acc))
而JS reduceRight
的论点被颠倒了:
reduceRight (fn, [head:tail], acc) = fn (reduceRight(fn, tail, acc), head)
javascript中的所有三个:
let nil = x => x === nil;
let reduce = (fn, [h=nil, ...t], a) => nil(h) ? a : reduce(fn, t, fn(a, h));
let foldr = (fn, [h=nil, ...t], a) => nil(h) ? a : fn(h, foldr(fn, t, a));
let reduceRight = (fn, [h=nil, ...t], a) => nil(h) ? a : fn(reduceRight(fn, t, a), h);
////
xs = [1,2,3,4]
list = (a, b) => `(${a} + ${b})`;
console.log(reduce(list, xs, ''));
console.log(foldr(list, xs, ''));
console.log(reduceRight(list, xs, ''));
&#13;
要根据map
来表达foldr
,您需要这样的内容:
let cons = (h, t) => [h, ...t];
let map = (fn, xs) => foldr((x, a) => cons(fn(x), a), xs, []);
答案 2 :(得分:0)
Here是一个reduceRight polyfill:
它使用的循环会减少而不是像解决方案中那样增量。
// Production steps of ECMA-262, Edition 5, 15.4.4.22
// Reference: http://es5.github.io/#x15.4.4.22
if ('function' !== typeof Array.prototype.reduceRight) {
Array.prototype.reduceRight = function(callback /*, initialValue*/) {
'use strict';
if (null === this || 'undefined' === typeof this) {
throw new TypeError('Array.prototype.reduce called on null or undefined');
}
if ('function' !== typeof callback) {
throw new TypeError(callback + ' is not a function');
}
var t = Object(this), len = t.length >>> 0, k = len - 1, value;
if (arguments.length >= 2) {
value = arguments[1];
} else {
while (k >= 0 && !(k in t)) {
k--;
}
if (k < 0) {
throw new TypeError('Reduce of empty array with no initial value');
}
value = t[k--];
}
for (; k >= 0; k--) {
if (k in t) {
value = callback(value, t[k], k, t);
}
}
return value;
};
}