Javascript 比较ECMA6集合是否相等

Javascript 比较ECMA6集合是否相等,javascript,set,ecmascript-6,Javascript,Set,Ecmascript 6,如何比较两个javascript集?我尝试使用==和===但都返回false a = new Set([1,2,3]); b = new Set([1,3,2]); a == b; //=> false a === b; //=> false 这两个集合是等价的,因为根据定义,至少通常不是。我看了一下,没有发现什么有用的东西。有人知道怎么做吗?试试这个: var a=新集合[1,2,3]; var b=新集合[1,3,2]; alerteqSeta,b;//符合事实的 函数方程{

如何比较两个javascript集?我尝试使用==和===但都返回false

a = new Set([1,2,3]);
b = new Set([1,3,2]);
a == b; //=> false
a === b; //=> false
这两个集合是等价的,因为根据定义,至少通常不是。我看了一下,没有发现什么有用的东西。有人知道怎么做吗?

试试这个:

var a=新集合[1,2,3]; var b=新集合[1,3,2]; alerteqSeta,b;//符合事实的 函数方程{ 如果as.size!==bs.size返回false; 对于变量a,as!bs.hasa返回false; 返回true; } 使用==,比较两个对象===

当使用==或===运算符比较两个对象时,总是会得到false。例如:

var a = b = new Set([1,2,3]); // NOTE: b will become a global variable
a == b; // <-- true: a and b share the same object reference
否则,==等于false,即使对象包含相同的值:

var a = new Set([1,2,3]);
var b = new Set([1,2,3]);
a == b; // <-- false: a and b are not referencing the same object

你可能需要考虑手工比较< /P> 在ECMAScript 6中,您可以事先将集合转换为数组,以便发现它们之间的差异:

function setsEqual(a,b){
    if (a.size !== b.size)
        return false;
    let aa = Array.from(a); 
    let bb = Array.from(b);
    return aa.filter(function(i){return bb.indexOf(i)<0}).length==0;
}

注意:Array.from是ECMAScript 6的标准功能之一,但现代浏览器并不广泛支持它。检查此处的兼容性表:

另一个答案可以正常工作;这是另一种选择

// Create function to check if an element is in a specified set.
function isIn(s)          { return elt => s.has(elt); }

// Check if one set contains another (all members of s2 are in s1).
function contains(s1, s2) { return [...s2] . every(isIn(s1)); }

// Set equality: a contains b, and b contains a
function eqSet(a, b)      { return contains(a, b) && contains(b, a); }

// Alternative, check size first
function eqSet(a, b)      { return a.size === b.size && contains(a, b); }
但是,请注意,这并不能进行深入的平等性比较。所以

eqSet(Set([{ a: 1 }], Set([{ a: 1 }])
将返回false。如果以上两个集合被认为是相等的,我们需要遍历这两个集合,对每个元素进行高质量的比较。我们规定存在一个平等的惯例。那么逻辑就是

// Find a member in "s" deeply equal to some value
function findDeepEqual(s, v) { return [...s] . find(m => deepEqual(v, m)); }

// See if sets s1 and s1 are deeply equal. DESTROYS s2.
function eqSetDeep(s1, s2) {
  return [...s1] . every(a1 => {
    var m1 = findDeepEqual(s2, a1);
    if (m1) { s2.delete(m1); return true; }
  }) && !s2.size;
}
其作用:对于s1的每个成员,寻找s2中一个完全相等的成员。如果找到,请将其删除,以便不能再次使用。如果s1中的所有元素都在s2中找到,并且s2已耗尽,则这两个集合是完全相等的。未经测试

您可能会发现这很有用:.

提供了0.isEqual,它可以进行深入的比较。如果你不想自己写,这是非常方便的。在lodash 4中,isEqual正确地比较了集合

const _ = require("lodash");

let s1 = new Set([1,2,3]);
let s2 = new Set([1,2,3]);
let s3 = new Set([2,3,4]);

console.log(_.isEqual(s1, s2)); // true
console.log(_.isEqual(s1, s3)); // false

1检查尺寸是否相等。如果不是,那么它们是不平等的

2迭代A的每个元素并签入B中存在的元素。如果一个元素失败,则返回不相等

3如果上述两个条件失败,则表示它们相等

设isEql=setA,setB=>{ 如果setA.size!==setB.size 返回false; setA.forEachval=>{ 如果!setB.hasval 返回false; }; 返回true; } 设setA=newset[1,2{ 3: 4 }]; 设setB=newset[2{ 3: 4 }, 1. ];
console.logisEqlsetA,setB 我在测试中遵循这种方法:

let setA = new Set(arrayA);
let setB = new Set(arrayB);
let diff = new Set([...setA].filter(x => !setB.has(x)));
expect([...diff].length).toBe(0);

这些解决方案都没有将预期的功能“带回”数据结构(如集合集)。在其当前状态下,Javascript对于此用途是无用的,因为超集将包含重复的子集,Javascript错误地将其视为不同的子集。我能想到的唯一解决方案是将每个子集转换为,对其进行排序,然后编码为例如JSON

解决方案 基本用法 var tojsostat=aset/*数组或set*/=>JSON.stringify[…new Setaset].sort; var fromjsostat=jset=>newsetjson.parsejset; var[s1,s2]=[新集合[1,2,3],新集合[3,2,1]; var[js1,js2]=[tojsstart[1,2,3],tojsstart[3,2,1]];//更好 var r=document.querySelectorAlltd:nth-child2; r[0]。innerHTML=toJsonSets1===toJsonSets2;//符合事实的 r[1]。innerHTML=toJsonSets1==toJsonSets2;//也是这样 r[2]。innerHTML=js1==js2;//符合事实的 r[3].innerHTML=js1==js2;//也是这样 //使其正常设置: console.logfromJsonSetjs1,fromJsonSetjs2;//类型已设置 td:nth-child2{颜色:红色;} toJsonSets1==toJsonSets2。。。 toJsonSets1==toJsonSets2。。。 js1==js2。。。 js1==js2。。。 您也可以尝试:

var a=新集合[1,2,3]; var b=新集合[1,3,2]; 设areSetsEqual=a,b=>a.size==b.size&&[…a];
我为Set.prototype.isEqual创建了一个快速多边形填充

Set.prototype.isEqual = function(otherSet) {
    if(this.size !== otherSet.size) return false;
    for(let item of this) if(!otherSet.has(item)) return false;
    return true;
}

根据公认的答案,假设支持Array.from,下面是一个单行程序:

function eqSet(a, b) {
    return a.size === b.size && Array.from(a).every(b.has.bind(b));
}

若集合只包含基元数据类型或集合内的对象具有引用相等性,那个么有一种更简单的方法


const isEqualSets=set1,set2=>set1.size==set2.size&&set1.size===new Set[…set1,…set2].size

根据@Aadit M Shah的回答进行了非常轻微的修改:

/**
 * check if two sets are equal in the sense that
 * they have a matching set of values.
 *
 * @param {Set} a 
 * @param {Set} b
 * @returns {Boolean} 
 */
const areSetsEqual = (a, b) => (
        (a.size === b.size) ? 
        [...a].every( value => b.has(value) ) : false
);
如果有人像我一样因为最新巴别塔的一些怪癖而有问题,我必须在这里添加一个明确的条件


另外,对于复数形式,我认为are只是更直观地大声朗读你的方法返回false的原因是因为你在比较两个不同的对象,即使它们的内容相同,因此比较两个不同的对象不是引用,而是对象总是返回falsy

下面的方法将两个集合合并为一个,只是愚蠢地比较大小。如果它是相同的,那么它是相同的:

const a1 = [1,2,3];
const a2 = [1,3,2];
const set1 = new Set(a1);
const set2 = new Set(a2);

const compareSet = new Set([...a1, ...a2]);
const isSetEqual = compareSet.size === set2.size && compareSet.size === set1.size;
console.log(isSetEqual);
优点:它非常简单和简短。没有外部库,只有Winnilla JS


缺点:它可能会比只遍历值慢一些,并且需要更多的空间。

可能会晚一些,但我通常会执行以下操作:

常数a=新集合[1,2,3]; 骗局 st b=新集合[1,3,2]; //选择1 console.loga.size==b.size&&newset[…a,…b].size==a.size //选择2

console.log[…a].sort.join==[…b].sort.join两个集合是两个不同的对象表示值相等,而不是对象相等。迭代并比较每个成员的值,如果所有值相同,则设置为same@dandavis对于集合,成员就是值。集合和映射确实有一个顺序,即插入顺序——不管出于什么原因:最糟糕的是,即使是新的集合[1,2,3]!=新集合[1,2,3]。这使得Javascript对于集合集合集毫无用处,因为超集将包含重复的子集。想到的唯一解决方法是将所有子集转换为数组,对每个数组进行排序,然后将每个数组编码为字符串,例如JSON。这不会无法识别不在a中的b成员吗?@torazaburo。跳过检查b的成员是否不在a中的最佳方法是检查a.size===b.size。将a.size===b.size放在第一位,以便在不必要时缩短单个元素的比较?如果大小不同,根据定义,集合不相等,因此最好先检查该条件。嗯,这里的另一个问题是,根据集合的性质,集合上的has操作设计得非常有效,这与数组上的indexOf操作不同。因此,将过滤器函数更改为return是有意义的!b、 哈西。这也将消除将b转换为数组的需要。我认为您应该将的名称更改为isPartOf或isIn或elem@Bergi我将函数名改为isIn。@DavidGiven是的,JavaScript中的集合按插入顺序迭代:每天我都更确信JavaScript是有史以来最糟糕的语言。每个人都必须发明自己的基本功能来应对其局限性,这是在ES6中,而我们是在2017年!为什么他们不能在Set对象的规范中添加如此频繁的函数呢@GhasanAl Sakkaf,我同意,也许TC39由科学家组成,但没有实用主义者……伟大的解决方案!如果你知道你刚刚得到了一组字符串或数字,它就会变成[…set1].sort.toString===[…set2].sort.toString===[…set2].sort.toString。幸运的是,我现在没有时间回顾这一点,但大多数使用内置默认值对js集合的键进行排序的解决方案都是错误的,因为js对象上没有总的顺序,例如,楠=楠,‘2’等一下。。。这只检查A是否有B没有的元素?它不检查B是否有A没有的元素。如果你试着a=[1,2,3]和b=[1,2,3,4],那么它们是一样的。所以我想你需要一个额外的检查,比如setA.size==setB.sized,这是一个更好的解决方案,因为它适合if条件。我喜欢这个解决方案的惯用性和可读性!谢谢@MaxThank让我发现了Array.every。但是,由于它不修改a,为什么需要使用[…a]进行复制?每个都是数组API的一部分,它不存在于集合或迭代器上,也不存在于真正的一行函数上,假设使用箭头函数和扩展运算符:eqSet=a,b=>a.size==b.size&&[…a]。everyb.has.bindbt此答案完全不正确。forEach方法中的return语句不会使父函数返回。
const a1 = [1,2,3];
const a2 = [1,3,2];
const set1 = new Set(a1);
const set2 = new Set(a2);

const compareSet = new Set([...a1, ...a2]);
const isSetEqual = compareSet.size === set2.size && compareSet.size === set1.size;
console.log(isSetEqual);