【问题标题】:Please how do i achieve the following using ramda请我如何使用 ramda 实现以下目标
【发布时间】:2020-08-04 08:49:16
【问题描述】:

我有一个随机的数字 1 到 5 数组,有时会随机出现 [1,1,1,1,2,2] 等。我的任务是始终找到出现次数最多的值。我使用名为 ramda here 的库在下面的 javascript 中实现了这一点。阅读文档后,我采用了如下解决方案。

// filter out duplication in array that way you can get the uniq represented numbers
const uniqueItems = R.uniq(params);

// use the unique numbers as keys and create a new array of object
 const mappedItemsWithRepresentations = map((a) => ({ color: a, rep: params.filter(b => b === a).length }), uniqueItems);

// and then finally, select the item with highest rep and return it key
const maxRepItem = mappedItemsWithRepresentations.reduce((acc, curr) => acc.rep > curr.rep ? acc : curr, []);

return maxRepItem.key; // gives me the correct value i need

但是,通过阅读文档中的更多内容并浏览示例here,我意识到有一种方法可以将上面的逻辑简单地与 ramda 结合起来。我尝试了无数次尝试,我能得到的最接近的是下面。

const getMaxRep = curry(pipe(uniq, map((a) => ({ color: a, rep: filter(b => b === a).length })), pipe(max(pathEq("rep")), tap(console.log))));

console.log("Max Rep here", getMaxRep(params));

我也尝试使用缩减功能here,但均无济于事。请我如何安排实现这一目标?任何帮助将不胜感激。

【问题讨论】:

    标签: functional-programming ramda.js


    【解决方案1】:

    Ramda 有 R.countBy 来获取出现次数。您可以将得到的 country 对象转换为对 [value, count],然后将其归约以找到计数最高的对:

    const { pipe, countBy, identity, toPairs, reduce, maxBy, last, head } = R
    
    const fn = pipe(
      countBy(identity), // count the occurrences 
      toPairs, // convert to pairs of [value, count]
      reduce(maxBy(last), [0, 0]), // reduce to find the maximum occurrence
      head, // get the actual value
      Number, // convert back to an number
    )
    
    const arr = [1,1,1,1,2,2]
    
    const result = fn(arr)
    
    console.log(result)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>

    将具有相同计数的值收集到数组中的想法略有不同。这将处理几个项目的频率相同的情况:

    const { pipe, countBy, identity, toPairs, invert, reduce, maxBy, last, head, map } = R
    
    const fn = pipe(
      countBy(identity), // count the occurrences 
      invert, // combine all values with the same count
      toPairs, // convert to pairs of [value, count]
      reduce(maxBy(head), [0, 0]), // reduce to find the maximum occurrence
      last, // get the actual values
      map(Number), // convert back to numbers
    )
    
    const arr = [1,1,1,1,2,2,3,3,3,3]
    
    const result = fn(arr)
    
    console.log(result)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>

    【讨论】:

    • 请看上面的代码,我认为 head 意味着获取第一个值,无论如何,在这种情况下如何转换以获得实际值。我正在尝试更好地理解代码。
    • head["1", 4] 条目中获取第一个值,产生“1”。然后我们申请Number 把它变成一个数字。
    • reduce 的结果是 ["1", "4"],我们需要第一项,因此是 head。斯科特更快:)
    【解决方案2】:

    不错的用例,试试这个:

    const maxReduce = reduce(maxBy(last), [0,0])
    const getMaxRep = pipe(countBy(identity), toPairs, maxReduce, head)
    
    console.log(getMaxRep([1,1,1,1,2,2]))
    

    countBy 是一个非常好的开始,遗憾的是 Ramda 不支持对象的 reduce,但我们可以使用 toPairs 函数转换为数组数组并完成工作。

    【讨论】:

      【解决方案3】:

      我并不完全清楚你要的是什么。

      但它可能是这样的:

      const maxRep = pipe (
        countBy (identity),
        toPairs,
        map (zipObj(['color', 'rep'])), 
        reduce (maxBy (prop ('rep')), {rep: -Infinity}),
      )
      
      const params = [1, 2, 3, 4, 2, 3, 5, 2, 3, 2, 1, 1, 4, 5, 5, 3, 2, 5, 1, 5, 2]
      
      console .log (
        maxRep (params)
      )
      <script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
      <script> const {pipe, countBy, identity, toPairs, map, zipObj, reduce, maxBy, prop} = R </script>

      我们从{1, 2, 3, 4, 5} 中提取的值列表开始,这些值以某种随机的、多次出现的顺序出现。

      使用countBy(identity),我们将原始列表更改为类似

      {"1": 4, "2": 6, "3": 4, "4": 2, "5": 5}
      

      与每个条目相关的计数。

      toPairs 将其格式化为类似

      的数组
      [["1", 4], ["2", 6], ["3", 4], ["4", 2], ["5", 5]]
      

      (你也可以在这里使用Object.entries。)

      然后通过调用map (zipObj (['color', 'rep'])),我们把它变成

      [{"color": "1", "rep": 4}, {"color": "2", "rep": 6}, ...]
      

      最后,我们使用maxBy (prop ('rep')) 减少结果,它选择具有最大rep 值的那个。对于 max 调用的初始值,我们创建了一个虚拟对象 {rep: -Infinity},它将比您列表中的任何一个都少。

      如果您还想保留最终的中间结构,可以将该函数重命名为 makeReps,删除管道中的最后一个函数,然后从中创建一个新的 maxRep

      那你就可以打电话了

      const reps = makeResps (params)
      const maxVal = maxRep (reps)
      

      两者都用。

      但所有这些都假定具有colorrep 属性的值就是您所需要的。如果您只需要计数,那么这里已经存在的其他解决方案可以处理得很好。

      【讨论】:

      • 这对先生很有帮助。谢谢你的时间
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-30
      • 2013-10-02
      相关资源
      最近更新 更多