我有一个很长的函数,此刻我需要一个函数的副本,唯一的区别是它要求大于而不是小于。因此,唯一的区别是>或<。
是否有(非凌乱的)方式使这种功能只是一个功能而不是这里的两个功能?
function(value, modifier) {
let result;
if (value > modifier) result = 10;
return result;
}
function(value, modifier) {
let result;
if (value < modifier) result = 10;
return result;
}
所以基本上,我需要一个大于/小于符号的条件。
编辑:要清楚,在理想的世界中,我想这样做:
myFunction(10, 5, >)
编辑:添加我实际功能的一部分以使事情更清楚。我希望可能有一种真正简单的方法来执行此操作,但似乎并非如此,实际功能的一部分可能会有所帮助:
function getEdges(colour) {
for (let x = 0; x < width; x++) {
for (let y = height - 1; y >= 0; y--) {
const data = getData(x,y);
if (data[0] < colour) {
edge.push(y);
break;
}
}
}
return edge;
}
还有另一个几乎相同的函数,其中唯一的区别是行if (data[0] > colour) {
大于或小于。
答案 0 :(得分:2)
如何将条件函数作为第三个参数传递?
function getEdges(colour, condition) {
for (let x = 0; x < width; x++) {
for (let y = height - 1; y >= 0; y--) {
const data = getData(x,y);
if (condition(data[0], colour)) {
edge.push(y);
break;
}
}
}
return edge;
}
调用该函数并传递所需条件。
小于:getEdges(color, (data, color) => color < data);
大于:getEdges(color, (data, color) => color > data);
答案 1 :(得分:2)
如果两个函数之间的唯一区别是比较,那么您可以提取它并将其作为参数
function getEdges(colour, comparator) {
for (let x = 0; x < width; x++) {
for (let y = height - 1; y >= 0; y--) {
const data = getData();
if (comparator(data[0], colour)) {
edge.push(y);
break;
}
}
}
return edge;
}
//call with less than
getEdges(someColour, (a, b) => a < b)
//call with greater than
getEdges(someColour, (a, b) => a > b)
您还可以将逻辑保留在一个函数中,并从中导出另外两个逻辑。这样,您无需维护多个代码块,仍然可以得到两个显式调用:
通过.bind
使用部分应用程序:
function getEdges(comparator, colour) {
// ^ ^ the two parameters are swapped
for (let x = 0; x < width; x++) {
for (let y = height - 1; y >= 0; y--) {
const data = getData();
if (comparator(data[0], colour)) {
edge.push(y);
break;
}
}
}
return edge;
}
//partial application
const getEdgesLessThan = getEdges.bind(null, (a, b) => a < b);
const getEdgesGreaterThan = getEdges.bind(null, (a, b) => a > b);
getEdgesLessThan(someColour)
getEdgesGreaterThan(someColour)
function getEdges(comparator) {
// ^---------
return function(colour) {// | taking two parameters
// ^ ----------
for (let x = 0; x < width; x++) {
for (let y = height - 1; y >= 0; y--) {
const data = getData();
if (comparator(data[0], colour)) {
edge.push(y);
break;
}
}
}
return edge;
}
}
//currying
const getEdgesLessThan = getEdges((a, b) => a < b);
const getEdgesGreaterThan = getEdges((a, b) => a > b);
getEdgesLessThan(someColour)
getEdgesGreaterThan(someColour)
答案 2 :(得分:1)
编辑:要清楚,在理想的世界中,我想这样做:
myFunction(10, 5, >)
您可以获得类似的东西:
const lt = (x, y) => x < y;
const gt = (x, y) => x > y;
function foo(value, modifier, compare) {
let result;
if (compare(value, modifier)) result = 10;
return result;
}
console.log(foo(2, 3, lt)); // 10
console.log(foo(3, 2, gt)); // 10
使用第二个示例:
const lt = (x, y) => x < y;
const gt = (x, y) => x > y;
const width = 3;
const height = 3;
const getData = (x, y) => [height * x + y];
console.log(getEdges(3, lt)); // [2]
console.log(getEdges(3, gt)); // [2,2]
function getEdges(colour, compare) {
const edge = [];
for (let x = 0; x < width; x++) {
for (let y = height - 1; y >= 0; y--) {
const data = getData(x, y);
if (compare(data[0], colour)) {
edge.push(y);
break;
}
}
}
return edge;
}
希望有帮助。
答案 3 :(得分:1)
基于评论中的对话,目的是在需要大于或小于比较时重新使用getEdges
函数。我添加了第二个参数来表明这一点,默认情况下将其设置为false
。 if语句是双重用途的,即在isGreater
标志设置为true时,它大于比较,而在isGreater
标志设置为false
中,则小于比较。 。其余逻辑按原样重复使用,没有重复。
function getEdgesInner(colour, isGreater = false) {
for (let x = 0; x < width; x++) {
for (let y = height - 1; y >= 0; y--) {
const data = getData(x,y);
if ((isGreater && data[0] > colour) || (!isGreater && data[0] < colour))
edge.push(y);
break;
}
}
}
return edge;
}
/* Public Api */
function getGreaterEdges(colour) { return getEdges(colour) }
function getLesserEdges(colour) { return getEdges(colour, true) }
答案 4 :(得分:1)
您可以保留运营商,并根据需要交换条款:
function getEdges(colour, operator) {
for (let x = 0; x < width; x++) {
for (let y = height - 1; y >= 0; y--) {
const data = getData();
const [a, b] = operator == '<' ? [data[0], colour] : [colour, data[0]];
if (a < b) {
edge.push(y);
break;
}
}
}
return edge;
}
编辑:
好,因此,如果您想使事情简单且在单独的函数中进行,只需对代码进行最少的更改,就可以像这样实现它:
function getEdges(colour, operator = '<') {
for (let x = 0; x < width; x++) {
for (let y = height - 1; y >= 0; y--) {
const data = getData();
const [a, b] = operator == '<' ? [data[0], colour] : [colour, data[0]];
if (a < b) {
edge.push(y);
break;
}
}
}
return edge;
}
签名getEdges(colour, operator = '<')
使operator
参数成为可选参数。如果您不将其传递给函数,它将采用默认值'<'
,这样您就不必在现有代码中进行任何更改。然后,您可以创建第二个函数,仅使用一个不同的参数即可重复使用原始函数:
function getEdgesGreaterThan(colour) {
return getEdges(colour, '>');
}
就在那里!希望对您有帮助!
答案 5 :(得分:1)
您可以尝试以下方式。就像您想要的原始样品一样!具有简短,时尚和美观的想法:
数学技巧:
function func(value, modifier, sign) {
let result, fc=sign=="<"?1:-1;
if (value*fc< modifier*fc) result = 10;
return result;
}
一个有用的JS功能:
function func(value, modifier, sign) {//this is slower probably
let result;
if (eval(value+sign+modifier)) result = 10;
return result;
}
用法(双向):
console.log(func(1, 2, "<"));
传递委托函数(用于比较):
function func(value, modifier, compF) {
let result;
if (compF(value, modifier)) result = 10;
return result;
}
用法:
console.log(func(1, 2, function(v, m){return v<m;}/*or equivalent lambda function*/));
答案 6 :(得分:0)
您应该添加带有条件的第三个参数,例如,字符串“ gt”表示Grater Than(>),“ lt”表示小于Than(<)
function(value, modifier, cond){
if(cond === "gt") return value > modifier ? 10 : undefined;
else if(cond === "lt") return value < modifier ? 10 : undefined;
}
编辑:我想出了一个更好的解决方案,适合您的最新问题。
let check = (value, modifier, cond)=>eval(value + cond + modifier) ? 10 : undefined
您在此处传递"<"
参数的">"
或cond
。
编辑2:
function getEdges(colour,cond) {
for (let x = 0; x < width; x++) {
for (let y = height - 1; y >= 0; y--) {
const data = getData(x,y);
let shoudPush = eval(data[0] + cond + colour) ? true : false
if(shouldPush) {
edge.push(y);
break;
}
}
}
return edge;
}
答案 7 :(得分:0)
function(value, modifier, type) {
let result;
if(type == ">") {
if (value > modifier) result = 10;
} else {
if (value < modifier) result = 10;
}
return result;
}
并通过字符串“ <”或“>”
传递类型答案 8 :(得分:0)
编辑:要清楚,在理想的世界中,我想这样做:
myFunction(10, 5, >)
您几乎可以使用eval做到这一点。尽管我对您的result
有点困惑,因为它可能返回未定义的值。
var myFunction = function(value, modifier, operation) {
var evalResult = eval(value + operation + modifier)
// I like ternary expression but could also be written as an if/else statement
return evalResult ? 10 : undefined
}
myFunction(10, 5, '<') // outputs undefined
myFunction(10, 5, '>') // outputs 10
请注意,评估可能很危险。 https://medium.com/@eric_lum/the-dangerous-world-of-javascripts-eval-and-encoded-strings-96fd902af2bd
编辑 嘿,我对您编辑的答案做了一个Codepen。 https://codepen.io/springborg/pen/ydayYa
我认为这与您建议的语法最接近。尽管除非您绝对确定不会暴露任何漏洞,否则我可能建议不要使用eval。
我的建议是使用Aditya Bhave的答案:) https://stackoverflow.com/a/56649540/1303205
答案 9 :(得分:0)
如果可重用性是您的最终目标,那么下面是一个很好的例子,说明了如何实现可重用性(某种功能编程风格)。
这种方法可以更大程度地重用代码。您可能希望在代码中的两点进行比较,然后根据上下文返回不同的值。
let functionalComparer = comp => modifier => result => value => {
return comp(value, modifier) ? result: undefined
}
// curry the crap out of it!
let gt = (x,y) => x > y
let gtComp = functionalComparer(gt)
let gt100 = gtComp(100)
let whenGt100ReturnString = gt100("more than 100!")
console.log(`
with value 99: ${whenGt100ReturnString(99)},
with value 101: ${whenGt100ReturnString(101)}
`)
let lt = (x,y) => x < y
let whenLt50ReturnFoo = functionalComparer(lt)(50)("FOO")
console.log(`
with value 49: ${whenLt50ReturnFoo(49)},
with value 51: ${whenLt50ReturnFoo(51)}
`)