[英]How to preload a Ramda curried function with item of an Array?
I have tagsList
which has about 20 tags, and termIds
which is an array of up to 3 tag ids. 我有tagsList
其具有约20的标签,和termIds
为不超过3的标签ID的阵列。
I'm trying to find the tags that match the ids in termIds in the tagsList, then set their borders. 我正在尝试在tagsList中找到与termIds中的ID匹配的标签,然后设置其边界。 Looking to avoid for loops and object-oriented programming in favor of a functional programming solution using Ramda curry . 寻求避免循环和面向对象的编程,转而使用Ramda curry的功能编程解决方案。
A tag in tagsList looks like : tagsList中的标签如下所示:
{
term: 'hi',
id: 123
}
And termIds could look like [123, 345, 678]
termIds可能看起来像[123, 345, 678]
123、345、678 [123, 345, 678]
When I find an id that matches, I give that tag a new key border1:true
, border2:true
etc... 当我找到一个匹配的ID时,给该标签一个新的键border1:true
, border2:true
等。
There is a list of tags, I have another array of termIds, goal is to see if any of the tags in the tagsList have an id that matches the termIds. 有一个标签列表,我还有另一个termIds数组,目标是查看tagsList中的任何标签是否具有与termIds匹配的ID。 If so give it a border1, if there are 2, then the 2nd gets border2 and finally 3 gets border 3. 如果是这样,给它一个border1,如果有2,那么第二个得到border2,最后3个得到border 3。
const checkId = _.curry((term_id, tag) => {
if (tag.id === term_id) {
console.log('match found!', tag)
}
});
const matchId = checkId(termIds);
const coloredTags = R.map(matchId, tagsList);
console.log('coloredTags', coloredTags)
return tagsList;
However this did not work because I am preloading the entire termIds array into the checkId
function. 但是,这不起作用,因为我将整个termIds数组预加载到checkId
函数中。 When instead I want to preload it with the individual items. 取而代之的是,我想预加载单个项目。
Next I tried this which I thought would work but getting a strange error: 接下来,我尝试了我认为可以解决的问题,但遇到一个奇怪的错误:
const matchId = R.forEach(checkId, termIds);
I think pure JS is enough to do it without Ramda. 我认为,没有Ramda的纯JS就足够了。 You just need a map : 您只需要一张地图:
var tagsList = [{term: 'hi', id: 123}, {term: 'ho', id: 152}, {term: 'hu', id: 345}, {term: 'ha', id: 72}]; var termIds = [123, 345, 678]; var i = 1; var results = tagsList.map(x => { if (termIds.indexOf(x.id) !== -1) x["border"+ (i++)] = true; return x; }); console.log(results);
This seems a reasonable approach: 这似乎是一种合理的方法:
R.map(tag => {
const index = R.indexOf(tag.id, termIds);
return (index > -1) ? R.assoc('border' + (index + 1), true, tag) : tag
})(tagsList);
//=> [
// {id: 123, term: "hi", border1: true},
// {id: 152, term: "ho"},
// {id: 345, term: "hu", border2: true},
// {id: 72, term: "ha"}
// ]
Although it could probably be made points-free with enough effort, it would likely be much less readable. 尽管可以通过足够的努力使它成为无分的,但它的可读性可能会大大降低。
You can see this in action on the Ramda REPL . 您可以在Ramda REPL上看到这一点。
If you want to make this into a reusable function, you can do it like this: 如果要将其变成可重用的函数,可以这样进行:
const addBorders = R.curry((terms, tags) => R.map(tag => {
const index = R.indexOf(tag.id, terms);
return (index > -1) ? R.assoc('border' + (index + 1), true, tag) : tag
})(tags))
addBorders(termIds, tagsList)
(The call to curry
is a Ramda habit. It means you can call addBorders(termIds)
and get back a reusable function that is looking for the tags. If you don't need that, you can skip the curry
wrapper.) (调用curry
是addBorders(termIds)
一种习惯。这意味着您可以调用addBorders(termIds)
并获取正在寻找标签的可重用函数。如果不需要,可以跳过curry
包装器。)
This version is also on the Ramda REPL . 该版本也在Ramda REPL上 。
Ah just figured it out, I had to curry the logic a 2nd time: 嗯,我终于明白了,我不得不第二次对逻辑进行讨论:
const matchId = R.curry((tag, term_id) => {
if (tag.id === Number(term_id)) {
console.log('match found!', tag)
}
});
const curried = R.curry((termIds, tag) => {
return R.map(matchId(tag), termIds);
});
const coloredTags = R.map(curried(termIds), tagsList);
console.log('coloredTags', coloredTags)
return tagsList;
So at the coloredTags
line, a tag from tagsLists goes into the curried(termIds). 因此,在coloredTags
行中,来自tagsLists的标签进入了curried(termIds)。 Ramda functions accept params from right to left. Ramda函数从右到左接受参数。
curried(termIds)
is already preloaded with the termIds array. curried(termIds)
已经预装了termIds数组。 So next in the const curried =
line, the termIds array and single tag make it in and the tag gets sent along into the next curried function matchId
, also the termIds
array is placed in the R.map
. 因此,接下来在const curried =
curried const curried =
行中,将termIds数组和单个标签放入其中,并将该标签发送到下一个咖喱函数matchId
,还将termIds
数组放置在R.map
。 Ramda list functions accept the Array of data as the right param. Ramda列表函数接受数据数组作为正确的参数。
Finally in matchId
I can make my check! 最后,在matchId
我可以进行检查!
UPDATE 更新
So the above answers the question I asked, about how to curry an item from an Array. 因此,以上内容回答了我提出的关于如何从Array中咖喱物品的问题。 However it caused a bug in my app. 但是,这导致了我的应用程序中的错误。 Since the termIds
array could hold up to 3 items, the coloredTags R.map
will run up to 3 times and create duplicate tags in my tagsList. 由于termIds
数组最多可容纳3个项目,因此coloredTags R.map
将最多运行3次,并在我的tagsList中创建重复的标签。
So just for completeness this is how I solved my in problem, much simpler and didn't need to use a double curried function. 因此,仅出于完整性考虑,这就是我解决问题的方式,它简单得多,并且不需要使用double curried函数。
const setTagColors = (tagsList, state) => {
const setBorder = (tag) => {
if (tag.id === Number(state.term_id_1)) {
tag.border1 = true;
} else if (tag.id === Number(state.term_id_2)) {
tag.border2 = true;
} else if (tag.id === Number(state.term_id_3)) {
tag.border3 = true;
}
return tag;
};
const coloredTags = R.map(setBorder, tagsList);
return state.term_id_1 ? coloredTags : tagsList;
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.