Lambda 如何在Ramda.js中比较两个集合?一个是否是另一个的超级集合?

Lambda 如何在Ramda.js中比较两个集合?一个是否是另一个的超级集合?,lambda,functional-programming,ramda.js,Lambda,Functional Programming,Ramda.js,在ramda.js中有没有比较两个集合的好方法,一个集合是否是另一个的超集/子集 比如说, const ss = new Set([1,2,3]) const s = new Set([1,2]) ss是s的超集(s是子集) 在ramda.js中有没有一种简单的方法来实现这一点?是的。不需要拉姆达 const isSubsetOf = (s1, s2) => new Set([ ...s1, ...s2 ]).size === s1.size; 如果s2是s1的子集,则返回true。

在ramda.js中有没有比较两个集合的好方法,一个集合是否是另一个的超集/子集

比如说,

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

const s = new Set([1,2])
ss
s
的超集(s是子集)


在ramda.js中有没有一种简单的方法来实现这一点?

是的。不需要拉姆达

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

如果s2是s1的子集,则返回true。改编自关于阵列的类似问题。

是。不需要拉姆达

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

如果s2是s1的子集,则返回true。改编自一个关于数组的类似问题。

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

考虑一下这个短路程序-

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

在另一个问答中,我们探讨了如何将函数方法添加到
集合.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))
如果您正在编写库、框架或工具等共享软件,则不建议修改本机原型。然而,如果这是您的程序,并且您不希望它成为其他人项目中的依赖项,那么修改任何原型(本机或其他)以满足您的需要并没有什么错

如果无法修改
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))

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

考虑一下这个短路程序-

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

在另一个问答中,我们探讨了如何将函数方法添加到
集合.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))
如果您正在编写库、框架或工具等共享软件,则不建议修改本机原型。然而,如果这是您的程序,并且您不希望它成为其他人项目中的依赖项,那么修改任何原型(本机或其他)以满足您的需要并没有什么错

如果无法修改
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复制:

函数isSubsetOf(集合,子集){
for(子集的变量元素){
如果(!set.has(elem))返回false;
}
返回true;
}

像完美主义者一样将其转化为无积分拉姆达:

//isSubsetOf::Set->Set->Boolean
常数isSubsetOf=
乌塞维思
(R.all)
([
R.bind(Set.prototype.has),
Array.from,
]);
const set1=新集合([1,2,3]);
const set2=新集合([1,2]);
发布(set1)(set2);//符合事实的

但我更想要一个无点但可读性更强的Ramda解决方案:

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

但实际上ES6版本足够优雅:

//isSubsetOf::Set->Set->Boolean
const isSubsetOf=s1=>s2=>
大堆
.来自(s2)
.every(x=>s1.has(x));


依我看,从逻辑上讲,简短的香草javascript非常优雅,可读性也很强,特别是对于这样一个小的实用程序函数,除非您非常喜欢FP并且无法抗拒使用FP库,或者您正在使用saccession.js来实现类型检查。

首先,让我们看看从MDN复制的非Ramda解决方案:

函数isSubsetOf(集合,子集){
for(子集的变量元素){
如果(!set.has(elem))返回false;
}
返回true;
}

像完美主义者一样将其转化为无积分拉姆达:

//isSubsetOf::Set->Set->Boolean
常数isSubsetOf=
乌塞维思
(R.all)
([
R.bind(Set.prototype.has),
Array.from,
]);
const set1=新集合([1,2,3]);
const set2=新集合([1,2]);
发布(set1)(set2);//符合事实的

但我更想要一个无点但可读性更强的Ramda解决方案:

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

但实际上ES6版本足够优雅:

//isSubsetOf::Set->Set->Boolean
const isSubsetOf=s1=>s2=>
大堆
.来自(s2)
.every(x=>s1.has(x));


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

谢谢您的回答。竖起大拇指。我仍然想知道是否有一个ramda.js方法。@tim我的意思是你可以用ramda来做这件事,但它不会更短,也不会更具可读性。它可能会更快,取决于集合的大小,这可能很重要,但这可能有很多原因。@JaredSmith取决于集合的大小,这种方法可能会慢很多。@Bergi当然,这是非常浪费的,但也很清楚和简洁。对于库代码来说不合适,但对于一次性代码来说可能是可以接受的。@tim:虽然完全可以使用Ramda函数来编写它——例如,按照Bergi的建议使用,
all
(s)=>(ss)=>R.all(s=>ss.has(s),[…s])
)--这样一种方法可能提供了vanilla JS无法提供的任何东西,只提供了简洁的:
(s)=>(ss)=>[…s]。每个(s=>ss.has))
。我是拉姆达的创始人之一,也是拉姆达的忠实粉丝,但这里似乎没有理由使用它。谢谢你的回答。竖起大拇指。我仍然想知道是否有一个ramda.js方法。@tim我的意思是你可以用ramda来做这件事,但它不会更短,也不会更具可读性。它可能会更快,这取决于你手机的大小