JavaScript 函数式编程 - 链接函数和使用匿名函数
JavaScript Functional Programming - Chaining Functions and using an anonymous function
当我在尝试将函数应用于值时遇到问题时,我在 CodeWars 上做题并练习一些函数式编程。
所以我制作了一个 pass() 函数,它接受一个函数作为参数,这样我就可以使用匿名函数来操纵该值,然后 return 它.因此,在这种情况下,它从 reduce 中获取值并将其传递给一个函数,以便它可以操纵该值然后 return 它。
它工作但是我真的不想向对象原型添加方法!
如何在保持函数链的同时以另一种方式执行此操作?
简单示例
Object.prototype.pass = function(fn) {
return fn(this);
};
var value = 1;
var new_value = value.pass(function(num){
return num + 1;
});
console.log(value, new_value); // Outputs: 1 2
上下文的 CodeWars 问题
Object.prototype.pass = function(fn) {
return fn(this)
};
function digPow(n, p) {
return n
.toString()
.split('')
.reduce(function(total, num, i) {
return total + Math.pow(parseInt(num), (p + i))
}, 0)
.pass(function(total) {
return (total % n == 0) ? Math.floor(total / n) : -1;
});
}
//digPow(89, 1) should return 1 since 8¹ + 9² = 89 = 89 * 1
console.log("Test Case 1 returns (", digPow(89, 1), ") should return 1")
//digPow(92, 1) should return -1 since there is no k such as 9¹ + 2² equals 92 * k
console.log("Test Case 2 returns (", digPow(92, 1), ") should return -1")
//digPow(695, 2) should return 2 since 6² + 9³ + 5⁴= 1390 = 695 * 2
console.log("Test Case 3 returns (", digPow(695, 2), ") should return 2")
//digPow(46288, 3) should return 51 since 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51
console.log("Test Case 4 returns (", digPow(46288, 3), ") should return 51")
代码战争说明
Some numbers have funny properties. For example:
89 --> 8¹ + 9² = 89 * 1
695 --> 6² + 9³ + 5⁴= 1390 = 695 * 2
46288 --> 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51 Given a
positive integer n written as abcd... (a, b, c, d... being digits) and
a positive integer p we want to find a positive integer k, if it
exists, such as the sum of the digits of n taken to the successive
powers of p is equal to k * n. In other words:
Is there an integer k such as : (a ^ p + b ^ (p+1) + c ^(p+2) + d ^
(p+3) + ...) = n * k If it is the case we will return k, if not return
-1.
Note: n, p will always be given as strictly positive integers.
解决方案就是不使用方法链接 - 您要应用于结果的功能不是它的方法。有多种解决方法:
一个简单的变量:
function digPow(n, p) {
const total = n
.toString()
.split('')
.reduce(function(total, num, i) {
return total + Math.pow(parseInt(num), (p + i))
}, 0);
return (total % n == 0) ? Math.floor(total / n) : -1;
}
一个 IIFE 调用(这种方法更适用于静态函数):
function digPow(n, p) {
return (function(total) {
return (total % n == 0) ? Math.floor(total / n) : -1;
}(n
.toString()
.split('')
.reduce(function(total, num, i) {
return total + Math.pow(parseInt(num), (p + i))
}, 0));
}
实验性 bind operator(与静态 "methods" 一起使用效果更好):
function digPow(n, p) {
return n
.toString()
.split('')
.reduce(function(total, num, i) {
return total + Math.pow(parseInt(num), (p + i))
}, 0)
:: function() {
return (this % n == 0) ? Math.floor(this / n) : -1;
}();
}
您也可以在 pass
"method" 中使用任何方法。
您也可以使用恒等仿函数。这为您提供了 a 可链式接口,但不会触及原生原型
const Identity = x => ({
runIdentity: x,
map: f => Identity(f(x))
})
const digPow = (n, p) =>
Identity(n)
.map(n => n.toString())
.map(str => str.split(''))
.map(nums => nums.reduce((total, num, i) =>
total + Math.pow(parseInt(num, 10), p + i), 0))
.map(total => total % n === 0 ? Math.floor(total / n) : -1)
.runIdentity
console.log(digPow(89, 1)) // 1
console.log(digPow(695, 2)) // 2
如果你定义了一些可重用的函数,它会稍微清理一下代码
const Identity = x => ({
runIdentity: x,
map: f => Identity(f(x))
})
const split = x => str => str.split(x)
const reduce = f => y => xs => xs.reduce(f, y)
const digPow = (n, p) =>
Identity(n)
.map(String)
.map(split(''))
.map(reduce((acc, x, i) => acc + Math.pow(Number(x), p + i)) (0))
.map(x => x % n === 0 ? Math.floor(x / n) : -1)
.runIdentity
console.log(digPow(89, 1)) // 1
console.log(digPow(695, 2)) // 2
当我在尝试将函数应用于值时遇到问题时,我在 CodeWars 上做题并练习一些函数式编程。
所以我制作了一个 pass() 函数,它接受一个函数作为参数,这样我就可以使用匿名函数来操纵该值,然后 return 它.因此,在这种情况下,它从 reduce 中获取值并将其传递给一个函数,以便它可以操纵该值然后 return 它。
它工作但是我真的不想向对象原型添加方法!
如何在保持函数链的同时以另一种方式执行此操作?
简单示例
Object.prototype.pass = function(fn) {
return fn(this);
};
var value = 1;
var new_value = value.pass(function(num){
return num + 1;
});
console.log(value, new_value); // Outputs: 1 2
上下文的 CodeWars 问题
Object.prototype.pass = function(fn) {
return fn(this)
};
function digPow(n, p) {
return n
.toString()
.split('')
.reduce(function(total, num, i) {
return total + Math.pow(parseInt(num), (p + i))
}, 0)
.pass(function(total) {
return (total % n == 0) ? Math.floor(total / n) : -1;
});
}
//digPow(89, 1) should return 1 since 8¹ + 9² = 89 = 89 * 1
console.log("Test Case 1 returns (", digPow(89, 1), ") should return 1")
//digPow(92, 1) should return -1 since there is no k such as 9¹ + 2² equals 92 * k
console.log("Test Case 2 returns (", digPow(92, 1), ") should return -1")
//digPow(695, 2) should return 2 since 6² + 9³ + 5⁴= 1390 = 695 * 2
console.log("Test Case 3 returns (", digPow(695, 2), ") should return 2")
//digPow(46288, 3) should return 51 since 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51
console.log("Test Case 4 returns (", digPow(46288, 3), ") should return 51")
代码战争说明
Some numbers have funny properties. For example:
89 --> 8¹ + 9² = 89 * 1
695 --> 6² + 9³ + 5⁴= 1390 = 695 * 2
46288 --> 4³ + 6⁴+ 2⁵ + 8⁶ + 8⁷ = 2360688 = 46288 * 51 Given a positive integer n written as abcd... (a, b, c, d... being digits) and a positive integer p we want to find a positive integer k, if it exists, such as the sum of the digits of n taken to the successive powers of p is equal to k * n. In other words:
Is there an integer k such as : (a ^ p + b ^ (p+1) + c ^(p+2) + d ^ (p+3) + ...) = n * k If it is the case we will return k, if not return -1.
Note: n, p will always be given as strictly positive integers.
解决方案就是不使用方法链接 - 您要应用于结果的功能不是它的方法。有多种解决方法:
一个简单的变量:
function digPow(n, p) { const total = n .toString() .split('') .reduce(function(total, num, i) { return total + Math.pow(parseInt(num), (p + i)) }, 0); return (total % n == 0) ? Math.floor(total / n) : -1; }
一个 IIFE 调用(这种方法更适用于静态函数):
function digPow(n, p) { return (function(total) { return (total % n == 0) ? Math.floor(total / n) : -1; }(n .toString() .split('') .reduce(function(total, num, i) { return total + Math.pow(parseInt(num), (p + i)) }, 0)); }
实验性 bind operator(与静态 "methods" 一起使用效果更好):
function digPow(n, p) { return n .toString() .split('') .reduce(function(total, num, i) { return total + Math.pow(parseInt(num), (p + i)) }, 0) :: function() { return (this % n == 0) ? Math.floor(this / n) : -1; }(); }
您也可以在 pass
"method" 中使用任何方法。
您也可以使用恒等仿函数。这为您提供了 a 可链式接口,但不会触及原生原型
const Identity = x => ({
runIdentity: x,
map: f => Identity(f(x))
})
const digPow = (n, p) =>
Identity(n)
.map(n => n.toString())
.map(str => str.split(''))
.map(nums => nums.reduce((total, num, i) =>
total + Math.pow(parseInt(num, 10), p + i), 0))
.map(total => total % n === 0 ? Math.floor(total / n) : -1)
.runIdentity
console.log(digPow(89, 1)) // 1
console.log(digPow(695, 2)) // 2
如果你定义了一些可重用的函数,它会稍微清理一下代码
const Identity = x => ({
runIdentity: x,
map: f => Identity(f(x))
})
const split = x => str => str.split(x)
const reduce = f => y => xs => xs.reduce(f, y)
const digPow = (n, p) =>
Identity(n)
.map(String)
.map(split(''))
.map(reduce((acc, x, i) => acc + Math.pow(Number(x), p + i)) (0))
.map(x => x % n === 0 ? Math.floor(x / n) : -1)
.runIdentity
console.log(digPow(89, 1)) // 1
console.log(digPow(695, 2)) // 2