如何比较 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])
ss
是 s
的超集(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 来实现类型检查。
有什么好的方法可以比较ramda.js中的2个集合,一个是另一个的超集/子集吗?
例如,
const ss = new Set([1,2,3])
const s = new Set([1,2])
ss
是 s
的超集(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 来实现类型检查。