请问我如何使用ramda实现以下目标

Please how do i achieve the following using ramda

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

// 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

但是,通过阅读文档中的更多内容并查看示例 ,我意识到有一种方法可以将上面的逻辑简单地与 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,但都无济于事。请问我该如何安排实现这一目标?任何帮助将不胜感激。

Ramda 有 R.countBy 来获取出现的次数。您可以将国家/地区的结果对象转换为对 [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>

不错的用例,试试这个:

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 函数转换为数组数组并完成工作。

我不太清楚你要的是什么。

但它可能是这样的:

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')) 对结果进行约简,它选择具有最大代表值的那个。对于 max 调用的初始值,我们创建了一个虚拟对象 {rep: -Infinity},它将比较小于您列表中的任何对象。

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

那你可以打电话

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

并同时使用。

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