function range(start, end) {
var acc = [];
for (var i = start; i < end; i++) {
acc.push(i);
}
return acc;
}
使用range函数和reduce方法,我需要重写阶乘函数。
function factorial(n) {
// YOUR CODE HERE
}
我得到了一个提示,首先在forEach中编写函数,然后用range和reduce重写它。这是我的尝试。
function factorial(n){
var product = 1;
n.forEach(function(x){
if(x===0){
return 1;}
product *= factorial(x-1);
});
return product;
}
factorial(4);
这是我的尝试。我知道这很乱,但我的问题是,当n只是一个数字而且每个数组是什么时,我如何使用forEach?因为他们希望我先使用每一个来编写阶乘函数,我需要使用基本情况吗?我还查看了MDN并尝试通过使用accumulator + currentValue来理解reduce,并想出了这个伪代码。
function factorial(n){
n.reduce(function(x){
x*range;
});
}
factorial(5)
如果参数不是数组,我不明白如何使用reduce。
答案 0 :(得分:2)
解决这个问题有两个步骤,第一步是生成一个数组以使用reduce方法,第二步实际上是使用reduce方法来找到我们的阶乘答案。
我们可以使用提供给我们的范围方法完成第一步。 range方法返回最小值(包括)和最大值(不包括)之间的所有整数值的数组。例如,如果我们致电range(1,5)
,则会返回[1,2,3,4]
。当我们想要执行阶乘操作时,我们希望将所有先前的整数值包括乘以当前值。要获取所有先前值和当前值的数组,我们可以使用
var factors = range(1,n+1);
在我们的阶乘函数开始时。
现在我们已经拥有了所有因素,我们可以使用reduce方法将它们相乘。 reduce方法将按顺序对数组的每个值执行提供的函数。在这种情况下,我们希望将所有因素相乘。我们可以使用
var multFactors = factors.reduce(function(a,b){
return a*b;
},1);
将数组中的每个值相乘。通过使用1
作为reduce方法的第二个参数,我们确保factorial(0)
不会导致任何错误(感谢@Eterm注意到这一点)
现在剩下的就是返回multFactors。
当所有这些都放在一起时,你最终得到了这个
function range(start, end) {
var acc = [];
for (var i = start; i < end; i++) {
acc.push(i);
}
return acc;
}
function factorial(n) {
var factors = range(1,n+1);
var multFactors = factors.reduce(function(a,b){
return a*b;
},1);
return multFactors;
}
修改强>
如果您想避免使用负因子进行错误,可以对n应用绝对值函数。
为此,我们可以更改
var factors = range(1,n+1);
到
var factors = range(1, Math.abs(n)+1);
采用负数的阶乘应该是未定义的,但是使用这个新行,我们通过使数字为正数来避免任何错误。如果要保留阶乘的符号,可以在设置multFactors之后但在返回之前添加这些行。
if(n < 0)
multFactors *= -1;
完成后,你最终得到这个(现在有评论,因为它更长)
function range(start, end) {
var acc = [];
for (var i = start; i < end; i++) {
acc.push(i);
}
return acc;
}
function factorial(n) {
//Get the factors
var factors = range(1, Math.abs(n)+1);
//Multiply all of the factors together
var multFactors = factors.reduce(function(a,b){
return a*b;
},1);
//if n was negative make the result negative
if(n < 0)
multFactors *= -1;
//return the calculated result
return multFactors;
}
希望这有帮助。
答案 1 :(得分:0)
当你说forEach is for Arrays but n is a number
时,你会发现什么。所以你需要构造你将循环的数组(后来减少)。
var n = 10;
var i = 0;
//use your "range" function to define an array from 2 to end.
var z = range(2, n + 1);
//Now we have an array we can reduce with multiplication initializing the accumulator to 1.
z.reduce(function(a,b){return a*b;}, 1);
reduce中的函数只是乘法,第二个参数初始化累加器。
此处不需要对0或1进行特殊处理,因为构造的数组将为空,而reduce将仅返回初始值1。
答案 2 :(得分:0)
您可以使用Array
。apply
并为给定的起始值和结束值创建包含范围。
然后通过乘法减少。
function range(start, end) {
return Array.apply(null, { length: end - start + 1 }).map(function (_, i) { return start + i; });
}
function multiply(a, b) { return a * b; }
var array = range(3, 7),
product = array.reduce(multiply);
console.log(array);
console.log(product);
console.log(range(1, 10).reduce(multiply));
.as-console-wrapper { max-height: 100% !important; top: 0; }
答案 3 :(得分:0)
只需按Nothing
,您可以执行以下操作;
Array.prototype.reduce()
&#13;
答案 4 :(得分:0)
这里还有很多其他答案可以提供解决问题的实用方法。我的答案是有目的的不切实际(用JavaScript编写),但旨在教你其他事情。
这个答案受到lambda演算的影响,它只有单个参数,单个表达式函数。剖析此代码将使您对高阶程序有深刻而深刻的理解。
我们首先定义Y-combinator,然后使用range
实现reduce
和Y
。然后我们最终可以实现factorial
。
const U = f => f (f)
const Y = U (h => f => f (x => h (h) (f) (x)))
const range = Y (h => acc => x => y =>
(x > y) ? acc : h ([...acc, x]) (x + 1) (y)
) ([]);
const reduce = Y (h => f => acc => ([x, ...xs]) =>
(x === undefined)
? acc
: h (f) (f (acc) (x)) (xs)
)
const mult = x => y => y * x
const factorial = x =>
reduce (mult) (1) (range (1) (x))
console.log(factorial (5)) // 120
console.log(factorial (6)) // 720
console.log(factorial (7)) // 5040
答案 5 :(得分:0)
我会做这样的事情:
const range = (start, end) => Array.from(
{ length: end - start },
(_, n) => start + n,
);
const product = (nums) => nums.reduce((a, b) => a * b);
const inc = (n) => n + 1;
const factorial = (num) => product(
range(1, inc(num)),
);
const expect = (given) => ({
toEqual(expected) {
console.assert(given === expected, `${given} === ${expected}`);
}
});
expect(factorial(5)).toEqual(120);
expect(factorial(6)).toEqual(720);