简体   繁体   English

如何使用数组项预加载Ramda咖喱函数?

[英]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:trueborder2:true等。

Goal: 目标:

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。


What I tried first: 我首先尝试的是:

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.) (调用curryaddBorders(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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM