【问题标题】:How to preload a Ramda curried function with item of an Array?如何使用数组项预加载 Ramda curried 函数?
【发布时间】:2017-05-10 04:05:30
【问题描述】:

我有 tagsList 大约有 20 个标签,termIds 是一个最多包含 3 个标签 ID 的数组。

我正在尝试在 tagsList 中找到与 termIds 中的 id 匹配的标签,然后设置它们的边界。希望避免 for 循环和面向对象编程,转而支持使用 Ramda curry 的函数式编程解决方案。

tagsList 中的标签看起来像:

{
    term: 'hi',
    id: 123
}

termIds 可能看起来像 [123, 345, 678]

当我找到一个匹配的 id 时,我给那个标签一个新的键 border1:trueborder2:true 等等...

目标:

有一个标签列表,我有另一个termIds数组,目标是查看tagsList中的任何标签是否有一个与termIds匹配的id。如果是,给它一个border1,如果有2个,那么第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;

但这不起作用,因为我将整个 termIds 数组预加载到 checkId 函数中。相反,我想用单个项目预加载它。

接下来我尝试了这个我认为可行的方法,但出现了一个奇怪的错误:

const matchId = R.forEach(checkId, termIds);

【问题讨论】:

  • 您的对象标签没有任何边框属性.....所以给我们标签列表和预期结果
  • 我刚刚添加了这些细节,是的,标签没有边框键,但我为前端 UI 模型添加了它。
  • 从您的角度来看,您几乎给出了解决方案的要素,但我们不知道问题出在哪里。你宁愿给我们你期望的结果。简而言之,给我们一个 tagList termIds 和预期 tagsList 的例子。否则我们会想知道每个元素有多少个边框......
  • 有一个标签列表,我有另一个termIds数组,目标是查看tagsList中的任何标签是否有一个与termIds匹配的id。如果是这样,给它一个边界1,如果有2,那么第二个得到边界2,最后3得到边界3。

标签: javascript arrays functional-programming ramda.js


【解决方案1】:

啊,刚刚想通了,我不得不第二次把逻辑搞砸了:

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;

所以在coloredTags 行,来自tagsLists 的标签进入curried(termIds)。 Ramda 函数接受从右到左的参数。

curried(termIds) 已经预加载了 termIds 数组。所以接下来在const curried = 行中,termIds 数组和单个标签进入,标签被发送到下一个柯里化函数matchIdtermIds 数组也被放置在R.map 中。 Ramda 列表函数接受数据数组作为正确的参数。

终于在matchId我可以检查了!


更新

所以上面回答了我提出的关于如何从数组中咖喱项目的问题。但是,它在我的应用程序中引起了错误。由于 termIds 数组最多可以容纳 3 个项目,coloredTags R.map 最多会运行 3 次,并在我的 tagsList 中创建重复的标签。

所以为了完整起见,这就是我解决问题的方法,简单得多,并且不需要使用双咖喱函数。

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;
};

【讨论】:

    【解决方案2】:

    我认为没有 Ramda 的纯 JS 就足够了。你只需要一张地图:

    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);

    【讨论】:

    • 谢谢,我喜欢使用 Ramda 的原因是它更具可读性... () !== -1 不是那么可读 :( 我们在应用程序的其他任何地方也使用 Ramda .
    【解决方案3】:

    这似乎是一个合理的方法:

    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"}
    // ]
    

    虽然只要付出足够的努力,它可能会变得无积分,但它的可读性可能会大大降低。

    您可以在 Ramda REPL 上看到这一点。

    如果你想把它变成一个可重用的函数,你可以这样做:

    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)
    

    (对curry的调用是Ramda的习惯。这意味着你可以调用addBorders(termIds)并返回一个寻找标签的可重用函数。如果你不需要,你可以跳过@987654327 @包装器。)

    这个版本也在Ramda REPL上。

    【讨论】:

      猜你喜欢
      • 2019-09-21
      • 1970-01-01
      • 2018-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多