[英]How to extract a function out of arr.map(elem => dict[elem])?
A function should do only one thing is considered a good practice when writing functions.一个 function 应该只做一件事被认为是编写函数时的一个好习惯。 However, I have a function that is already very minimal, but nevertheless I think it can be further extracted, but I don't know how this can be done.
但是,我有一个已经非常小的 function,但我认为它可以进一步提取,但我不知道如何做到这一点。
The following recode()
function replaces array values according to a look-up dictionary.以下
recode()
function 根据查找字典替换数组值。
function recode(arr, dict) {
return arr.map(elem => dict[elem])
}
Example to how it works:它是如何工作的示例:
// input data to be recoded
const myArr = ['eggplant', 'tomato', 'carrot', 'cabbage'];
// look-up dictionary
const myDict = {
eggplant: 'purple',
tomato: 'red',
carrot: 'orange',
};
const result1 = recode(myArr, myDict)
console.log(result1) // => ["purple", "red", "orange", undefined]
The way I see it, the current recode()
function does two things:在我看来,当前的
recode()
function 做了两件事:
elem => dict[elem]
;elem => dict[elem]
; andarr
arr
My question is whether I can extract an individual function for elem => dict[elem]
, and supply that function to arr.map()
.我的问题是我是否可以为
elem => dict[elem]
提取个人 function ,并将该 function 提供给arr.map()
。 I imagine something along the lines of:我想象的是:
// pseudo-code
function funcInner() {...}
function recode(arr, dict) {
return arr.map(funcInner)
}
This way, I will have one function that does only the replacement, and another that only maps over arr
.这样,我将有一个 function 只做替换,另一个只映射
arr
。
EDIT编辑
To address the comments, I would like to make an analogy.针对评论,我想打个比方。 Let's consider a function that doubles array values.
让我们考虑一个将数组值加倍的 function。
function doubleArray(arr) {
return arr.map(x => x * 2)
}
Some folks here might say that doubleArray()
is already doing one thing.这里有些人可能会说
doubleArray()
已经在做一件事了。 However, we could still extract:但是,我们仍然可以提取:
const doubleNumber = x => x * 2;
function doubleArray2(arr) {
return arr.map(doubleNumber)
}
As far as I understand, doubleArray()
did two things (double & map), whereas doubleArray2()
does only one thing (map) and doubleNumber()
does one thing (doubles).据我所知,
doubleArray()
做了两件事(double 和 map),而doubleArray2()
只做了一件事(map)而doubleNumber()
做了一件事(double)。 Therefore, doubleArray()
is not a meaningless refactoring.因此,
doubleArray()
并不是无意义的重构。
Furthermore, once we have a function that does one thing, it promotes more accurate unit tests we can write for it.此外,一旦我们有一个 function 做一件事,它就会促进我们可以为它编写更准确的单元测试。
Lastly, if we translated this code to typescript (which I didn't focus on in this question), then the input type in doubleNumber()
is different than the input type in doubleArray()
.最后,如果我们将这段代码翻译成typescript (我在这个问题中没有重点关注),那么
doubleNumber()
中的输入类型与doubleArray()
中的输入类型不同。 So that's another reason why I would prefer to extract.所以这是我更喜欢提取的另一个原因。
I'm very new to javascript, but this is the way I understand it.我对 javascript 很陌生,但这是我的理解方式。 So my question about
recode()
was within this context.所以我关于
recode()
的问题是在这种情况下。
To answer your question:回答你的问题:
function recode(arr, dict) {
return arr.map(elem => funcInner(elem,dict));
};
function funcInner(elem, dict) {
return dict[elem];
}
But i agree with the others commenting on you question, this may be a little overkill.但我同意其他人对你问题的评论,这可能有点矫枉过正。 Your choice.
你的选择。
In essence recode
is being used a wrapper around arr.map()
.本质上,
recode
被用作arr.map()
的包装器。 This could also be achieved by assigning recode
to a function returned by calling the Function.bind()
method .这也可以通过将
recode
分配给调用Function.bind()
方法返回的 function 来实现。
const recode = myArr.map.bind(myArr, elem => myDict[elem]);
myArr
needs to be passed as the first parameter to bind the context of the array. myArr
需要作为第一个参数传递来绑定数组的上下文。
// input data to be recoded const myArr = ['eggplant', 'tomato', 'carrot', 'cabbage']; // look-up dictionary const myDict = { eggplant: 'purple', tomato: 'red', carrot: 'orange', }; const recode = myArr.map.bind(myArr, elem => myDict[elem]); const result1 = recode(myArr, myDict) console.log(result1) // => ["purple", "red", "orange", undefined]
But perhaps it is simpler just to call .map()
directly:但也许直接调用
.map()
更简单:
// input data to be recoded const myArr = ['eggplant', 'tomato', 'carrot', 'cabbage']; // look-up dictionary const myDict = { eggplant: 'purple', tomato: 'red', carrot: 'orange', }; const result1 = myArr.map(elem => myDict[elem]) console.log(result1) // => ["purple", "red", "orange", undefined]
If there is a desire to have a user-supplied callback, then the ES-6 default parameters could be used:如果希望有一个用户提供的回调,那么可以使用ES-6 默认参数:
function recode(myArr, myDict, callback = elem => myDict[elem]) { return myArr.map(callback); } // input data to be recoded const myArr = ['eggplant', 'tomato', 'carrot', 'cabbage']; // look-up dictionary const myDict = { eggplant: 'purple', tomato: 'red', carrot: 'orange', }; const result1 = recode(myArr, myDict) console.log(result1) // => ["purple", "red", "orange", undefined] const result2 = recode(myArr, myDict, elem => myDict[elem] + 'a') console.log(result2) // => ["purplea", "reda", "orangea", "undefineda"]
A slight variation on Daniel's answer : Have the other function return a function that can be used as callback for Array#map
: Daniel 的回答略有不同:让另一个 function 返回一个 function 可以用作
Array#map
的回调:
function createMapper(dict) {
return elem => dict[elem];
}
function recode(arr, dict) {
return arr.map(createMapper(dict));
}
But I would also question whether this is really an improvement over your original code.但我也会质疑这是否真的是对您原始代码的改进。
You do not need to extract in your case, thats why arrow functions exist.你不需要在你的情况下提取,这就是箭头函数存在的原因。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.