[英]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.