如何比较 Ramda.js 中的 2 组?一个是否是另一个的超集?

How to compare 2 sets in Ramda.js? Whether one is a super set of another?

有什么好的方法可以比较ramda.js中的2个集合,一个是另一个的超集/子集吗?

例如,

const ss = new Set([1,2,3])

const s = new Set([1,2])

sss 的超集(s 是子集)。

在 ramda.js 中有实现此目的的简单方法吗?

是的。不需要 ramda。

const isSubsetOf = (s1, s2) => new Set([ ...s1, ...s2 ]).size === s1.size;

Returns 如果 s2 是 s1 的子集则为真。改编自 this answer 关于数组的类似问题。

Jared 的回答很简洁,但如果要比较的集合相当大,它就不是一个有效的算法。

考虑这个短路方案-

const isSubsetOf = (super, sub) => {
  for (const s of sub)
    if (!super.has(s))
      return false
  return true
}

在另一个问答 How to map/reduce/filter a Set in JavaScript? 中,我们探讨了如何向 Set.prototype 添加函数式方法。对我们特别有用的一个是 Set.prototype.every -

Set.prototype.every = function every(f) {
  for (const v of this) if (!f(v)) return false
  return true
}

这将允许您将程序重写为 -

const isSubsetOf = (super, sub) =>
  sub.every(s => super.has(s))

如果您正在编写库、框架或工具等共享软件,则不建议修改本机原型。但是,如果这是您的程序并且您不希望它成为其他人项目的依赖项,那么修改 any 原型(本机或其他)以满足您的需要并没有错。

如果不能修改Set.prototype,函数API还是可以的-

const setEvery = (set, f) => {
  for (const v of this) if (!f(v)) return false
  return true
}

const isSubsetOf = (super, sub) =>
  setEvery(sub, s => super.has(s))

首先,让我们看一个非 Ramda 的解决方案,从 MDN 复制: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set

function isSubsetOf(set, subset) {
  for (var elem of subset) {
    if (!set.has(elem)) return false;
  }
  return true;
}

像完美主义者一样把它翻译成无点的Ramda:

// isSubsetOf :: Set -> Set -> Boolean
const isSubsetOf = 
  R.useWith
    (R.all)
    ([
      R.bind (Set.prototype.has),
      Array.from,
    ]);

const set1 = new Set([1, 2, 3]);
const set2 = new Set([1, 2]);
isSubsetOf (set1) (set2); // true

但我更想要一个不那么无意义但更具可读性的 Ramda 解决方案:

// isSubsetOf :: Set -> Set -> Boolean
const isSubsetOf = s1 => s2 =>
  R.all
    (x => s1.has(x))
    (Array.from(s2));

不过其实一个ES6版本就足够优雅了:

// isSubsetOf :: Set -> Set -> Boolean
const isSubsetOf = s1 => s2 => 
  Array
    .from(s2)
    .every(x => s1.has(x));

IMO,从逻辑上讲,简短的香草 javascript 足够优雅和可读,特别是对于像这样的小实用函数,除非你非常喜欢 FP 并且无法抗拒为它使用 FP 库,或者您正在使用 sanctuary.js 来实现类型检查。