繁体   English   中英

与 JavaScript 中的 Array.reduce() 相反

[英]Opposite of Array.reduce() in javascript

Array.reduce() 获取一个数组并将数组中的元素与累加器组合,直到所有元素都被消耗完。

是否有一个函数(在其他语言中通常称为“展开”)以一个值开始并不断生成元素,直到产生一个完整的数组(累加器耗尽)?

我正在尝试将其作为任意基数之间转换的一部分。 我拥有的代码如下,但我想消除原始循环。

var dstAlphabet = "0123456789ABCDEFGH";
var dstBase = dstAlphabet.length;
var wet = BigInteger(100308923948716816384684613592839);
var digits_reversed = [];
while (wet.isPositive())
{
  // var digitVal = wet % dstBase
  var divRem = wet.divRem(dstBase); // [result of division, remainder]
  wet = divRem[0];
  digits_reversed.push(dstAlphabet.charAt(divRem[1].toJSValue()));
}

return digits_reversed.reverse().join("");

 // These days you can do it in one line: const unfold = (accumulator, length) => length <= 0 ? accumulator : unfold([length, ...accumulator], length -1) // invoke it like this: const results = unfold([], 5) // expected results: 1,2,3,4,5 console.log(results.join(','))

由于我们正在寻找一种将给定数量的元素生成为数组的简洁方法,因此这个“展开”函数通过递归来实现。

第一个参数是累加器数组。 这需要传递,并最终在它包含整个集合时返回。 第二个参数是限制器。 这是您用来确定结果数组的尺寸。

在每次调用中,我们首先测试是否达到了基本情况。 如果是这样,答案很简单:只需返回给定的数组。 对于一般情况,我们再次展开,但使用较小的值,因此我们将一个值添加到累加器,并减少长度。

由于我们使用了扩展运算符和“计算如果”,因此函数很简洁。 使用箭头样式还可以让我们避免使用“function”和“return”关键字以及花括号。 所以整个事情都是单行的。

我基本上使用这种技术作为 React JSX 的 for 循环替代品,其中所有内容都需要是一个表达式 (Array.map())。

Javascript 中Array#reduce的对立面是Array.from (或者扩展语法)。 您可以将它与任何可迭代对象一起使用以生成数组:

array = Array.from(iterator); // same as array = [...iterator];

可以通过调用生成器函数来创建迭代器:

iterator = generate(params);

生成器函数使用特殊关键字yield来返回它们的结果(或使用yield*来返回另一个迭代的所有结果)。 一旦返回,它们就会耗尽:

 function* convertBase(wet, alphabet) { const base = BigInt(alphabet.length); wet = BigInt(wet); while (wet > 0) { const digitVal = Number(wet % base); wet = wet / base; yield alphabet.charAt(digitVal); } } console.log(Array.from(convertBase(100308923948716816384684613592839, "0123456789ABCDEFGH")).reverse().join(""));

或者,您可以在没有生成器函数的情况下自己实现迭代器:

 console.log(Array.from({ wet: BigInt(100308923948716816384684613592839), base: BigInt(18), alphabet: "0123456789ABCDEFGH", [Symbol.iterator]: function() { return this; }, next: function() { if (this.wet > 0) { const digitVal = Number(this.wet % this.base); this.wet = this.wet / this.base; return {value: this.alphabet.charAt(digitVal)}; } else { return {done: true}; } } }).reverse().join(""));

tewathia 的评论似乎是一种惯用的方式,但我想如果你想以艰难的方式做到这一点,你可以编写自己的递归原语,例如:

function unreduce(accumulator, operation, stopPredicate, ret) {
    return helper([accumulator, ret])[1]

    function helper(vals) {
        if (stopPredicate(vals[0])) return vals[1];

        return helper(operation(vals[0], vals[1]));
    }
}

您可能需要对其进行一些this以保留回调。

我不确定那有多好。 operation回调需要同时更新累加器和返回值,这有点尴尬。 外部函数无法避免operation不得不返回一个长度为 2 的数组。

array.map((..) => { return [ .. ]; }).flat(1);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM