我还在学习JavaScript中的函数式编程,我很喜欢使用Ramda。
我有两个数组。我想检查它们是否具有相同的值,与订单无关。我认为这可以用equals
完成。但显然
R.equals([1, 2], [2, 1]) // false
有没有一种有效的方法来检查两个数组是否相等?我的数组由对象组成,如果1 <X <10,则可以容纳X * 10E4值。
它不起作用的原因 - 除了Ramda函数被命名为equals
而不是isEqual
这一事实之外,Arrays是本质上有序的容器。 [1, 2]
与[2, 1]
有重大差异。
标准的无序容器是Set
。不幸的是,这是基于引用相等,因此它可以获得Ramda认为相同的项目的多个副本。所以最明显的答案将无法正常运作:
// ** Broken -- do not use **
const eqValues = (a1, a2) => R.equals(new Set(a1), new Set(a2))
console.log(eqValues(
[{x: 1}, {x: 2}],
[{x: 1}, {x: 3}]
)) //=> false
console.log(eqValues(
[{x: 1}, {x: 2}],
[{x: 2}, {x: 1}]
)) //=> true
因为在这种情况下由于长度检查会失败:
console.log(eqValues(
[{x: 1}, {x: 2}, {x: 2}],
[{x: 2}, {x: 1}]
)) //=> false, but should be true, since {x: 2} is the same as {x: 2}
拉姆达没有暴露其内部_Set
类型 - 也许它应该 - 但it uses them在difference
这样的功能,并通过symmetricDifference
。这些是用于测试其值相等的值的适当函数。
所以我的答案与bug中的答案相似,但我会用不同的方式说出来:
const eqValues = compose(isEmpty, symmetricDifference)
console.log(eqValues(
[{x: 1}, {x: 2}],
[{x: 1}, {x: 3}]
)) //=> false
console.log(eqValues(
[{x: 1}, {x: 2}],
[{x: 2}, {x: 1}]
)) //=> true
console.log(eqValues(
[{x: 1}, {x: 2}],
[{x: 2}, {x: 1}, {x: 1}]
)) //=> true
<script src="https://bundle.run/[email protected]"></script><script>
const {compose, isEmpty, symmetricDifference} = ramda; </script>
但是,如果你需要测试多重性 - 也就是说,arr1
包含{x: 42}
和arr2
的两个副本只有一个,所以它们是不同的 - 然后我会使用来自customcommander的答案。
Ramda有很多方法可以实现这一目标
想到的是
R.length([1,2]) === R.length([2,1]) && R.isEmpty(R.symmetricDifference([1,2], [2,1]))
编辑:使用R.difference
而不是R.symmetricDifference
不起作用,因为第一个只返回第一个列表中未包含在第二个列表中的元素。
R.difference([1,2], [2,1,3]) // -> []