javascript - 如何以函数式JS方式使用Ramda实现LoDash的sampleSize?

标签 javascript functional-programming ramda.js

我正在尝试实现 LoDash 的 sampleSize函数式方式使用 Ramda 的方法。

有什么想法吗?除了从给定数组中获取 randomIndex 之外,我完全陷入困境。如何使用 Ramda 进行递归循环?

因此,该函数将如下所示:

export const sampleSize = curry((size, list) => compose(
  // two paths of code
  // one to splice messages at the randomIndex
  // recursion with the spliced array until length === size
  randomIndex
)(list))

最佳答案

我可能不会使用 Ramda 来执行此操作。请注意,我是 Ramda 的创始人之一,也是 Ramda 的忠实粉丝。但 Ramda 是为函数式编程而设计的。函数式编程的主要原则之一是使用纯函数,纯函数在其参数之外不使用任何输入,并且除了返回值之外没有任何作用。对于相同的输入,它们应该始终返回相同的输出。当代码应该随机执行某些操作时,这将不起作用。1

您可以使用类似 lodash 所做的代码,这是 Fisher-Yates shuffle 的早期返回版本。或者你可以使用类似这样的东西,它也按照原始数组中找到的顺序保留其结果:

const sampleSize = (size, list, collected = []) => size < 1 || list.length < 1
  ? collected
  : size >= list.length
    ? [...collected, ...list] // or throw error?
    : Math.random() < size / list.length
      ? sampleSize(size -1, list.slice(1), [...collected, list[0]])
      : sampleSize(size, list.slice(1), collected)

console.log(sampleSize(4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
console.log(sampleSize(4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
console.log(sampleSize(4, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))

console.log(sampleSize(0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
console.log(sampleSize(10, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))
console.log(sampleSize(20, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]))

这是匆忙写的,可能有错误,但应该非常接近。这个想法是一次检查每个元素,看看是否应该包含它,根据剩余要包含的元素以及列表中剩余的元素来调整机会。

Fisher-Yates 版本会比这更有效,特别是因为它使用递归,即使现在规范已经要求它好几年了,但即使在今天,引擎也可能无法有效优化它。但 Fisher-Yates 并不保留原始排序顺序。如果您想要这样,这个可能适合您。

<小时/>

1 请注意,在某一时刻,Ramda 确实有 random number extension ,但这早已被废弃了。它使用了可重复的伪随机数生成器,这听起来几乎像是矛盾的说法,但在使用纯函数时是有意义的。

关于javascript - 如何以函数式JS方式使用Ramda实现LoDash的sampleSize?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54274045/

相关文章:

r - 函数的函数总是返回 0-R

javascript - ramda 进化函数示例

javascript - Ramda compose 传递多个参数

javascript - 在模板中查找 key 失败

javascript - 如何让我的导航栏在滚动时变成半透明?

javascript - 单击按钮,计算总价(Javascript)

javascript - 如何在 Meteor 中只允许插入和更新某些文档字段?

javascript - 如何在 JavaScript 中使用 pointfree 风格而不失可读性?

recursion - 为什么 lua 不允许本地 lambda 函数递归调用自己?

javascript - 如何删除对象中特定键的所有实例?