你如何比较两个 JavaScript 集合?我尝试使用 ==
和 ===
,但两者都返回 false。
a = new Set([1,2,3]);
b = new Set([1,3,2]);
a == b; //=> false
a === b; //=> false
这两组是等价的,因为根据定义,集合没有顺序(至少通常情况下是这样)。我查看了MDN 上 Set 的文档,但没有找到有用的信息。有人知道怎么做吗?
你如何比较两个 JavaScript 集合?我尝试使用 ==
和 ===
,但两者都返回 false。
a = new Set([1,2,3]);
b = new Set([1,3,2]);
a == b; //=> false
a === b; //=> false
这两组是等价的,因为根据定义,集合没有顺序(至少通常情况下是这样)。我查看了MDN 上 Set 的文档,但没有找到有用的信息。有人知道怎么做吗?
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);
优点: 它非常简单和短小。没有外部库,只使用vanilla JS。
缺点: 可能比仅迭代值要慢,并且需要更多的空间。
基于@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
);
如果还有其他人像我一样因为最新版本的babel出现了一些怪异问题,那么就必须在这里添加一个明确的条件语句来解决问题。
(此外,我认为对于复数时,使用are
更容易口头阅读。)
我为Set.prototype.isEqual()创建了一个快速的polyfill。
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;
}
Github Gist - Set.prototype.isEqual
{{链接1:Github Gist - Set.prototype.isEqual}}
equals(set1, set2)
const s1 = new Set([1, 2, 3]);
const s2 = new Set([3, 1, 2]);
console.log( R.equals(s1, s2) );
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.27.1/ramda.min.js"></script>
现有的答案都没有检查Set的插入顺序,所以这里提供一个可以做到的方法。它使用lodash的_.isEqualWith
进行浅层次检查(因为_.isEqual
会进行深度检查,而且对于Set来说速度较慢)。
import isEqualWith from 'lodash/isEqualWith';
export function setsAreEqual (setA: Set<unknown>, setB: Set<unknown>): boolean {
return isEqualWith(setA, setB, (a: unknown, b: unknown) => {
if (a === setA) return undefined;
return a === b;
});
}
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);
a=[1,2,3]
和b=[1,2,3,4]
,它会说它们是相同的。所以我猜你需要额外的检查,例如setA.size === setB.size
。 - user993683 ===
:function setEquals(x, y, comparer) {
if (!comparer) {
return x.size === y.size
&& [...x].every(a => y.has(a));
}
return x.size === y.size
&& [...x].every(a => [...y].some(b => comparer(a, b)));
}
如果您不传递比较器,这仍将与其他方法相同,但您可以选择传递自定义比较方法,例如 (a, b) => a.id === b.id
。
1)检查尺寸是否相等。如果不相等,则它们不相等。
2)迭代A的每个元素并检查是否存在于B中。如果有一个失败,则返回unequal
3)如果上述两个条件失败,那么它们相等。
let isEql = (setA, setB) => {
if (setA.size !== setB.size)
return false;
setA.forEach((val) => {
if (!setB.has(val))
return false;
});
return true;
}
let setA = new Set([1, 2, {
3: 4
}]);
let setB = new Set([2, {
3: 4
},
1
]);
console.log(isEql(setA, setB));
2) 方法二
let isEql = (A, B) => {
return JSON.stringify([...A].sort()) == JSON.stringify([...B].sort());
}
let res = isEql(new Set([1, 2, {3:4}]), new Set([{3:4},1, 2]));
console.log(res);
forEach
方法中的返回语句不会使父函数返回。 - xaviert
new Set([1,2,3]) != new Set([1,2,3])
。这使得JavaScript中的 Set 对于“集合的集合”而言毫无用处,因为超级集合将包含重复的子集。唯一想到的解决方法是将所有子集转换为数组,对每个数组进行排序,然后将每个数组编码为字符串(例如JSON)。 - 7vujy0f0hy