Ramda:检查两个数组是否相等
Ramda: Check if two arrays are equal
我仍在 JavaScript 学习函数式编程,我非常喜欢使用 Ramda。
我有两个数组。我想检查它们是否具有相同的值,与顺序无关。我认为这可以用 equals
来完成。但显然
R.equals([1, 2], [2, 1]) // false
有没有一种有效的方法来检查两个数组是否相等?我的数组由对象组成,并且最多可以容纳 X * 10E4 个值(如果这与 1 < X < 10 相关)。
使用 Ramda 有很多方法可以实现这一点
想到的是
R.length([1,2]) === R.length([2,1]) && R.isEmpty(R.symmetricDifference([1,2], [2,1]))
edit:使用 R.difference
而不是 R.symmetricDifference
是行不通的,因为第一个只有 returns 中的元素不包含在第二个列表中的第一个列表。
R.difference([1,2], [2,1,3]) // -> []
您可以使用 countBy
构建一个 "profile" 数组:
countBy(identity, [1, 2]);
//=> {"1": 1, "2": 1}
countBy(identity, [2, 1]);
//=> {"1": 1, "2": 1}
然后你可以比较两个配置文件 eqBy
:
eqBy(countBy(identity), [1,2], [2,1])
//=> true
它不能那样工作的原因——除了 Ramda 函数被命名为 equals
而不是 isEqual
之外——数组是本质上有序的容器。 [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}
Ramda 不公开其内部 _Set
类型——也许应该公开——但是 it uses them in such functions as difference
, and through that in 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/ramda@0.26.1"></script><script>
const {compose, isEmpty, symmetricDifference} = ramda; </script>
但是,如果您需要测试多重性——也就是说,arr1
包含 {x: 42}
的两个副本,而 arr2
只有一个,所以它们是不同的——那么我会使用 customcommander 的答案。
我仍在 JavaScript 学习函数式编程,我非常喜欢使用 Ramda。
我有两个数组。我想检查它们是否具有相同的值,与顺序无关。我认为这可以用 equals
来完成。但显然
R.equals([1, 2], [2, 1]) // false
有没有一种有效的方法来检查两个数组是否相等?我的数组由对象组成,并且最多可以容纳 X * 10E4 个值(如果这与 1 < X < 10 相关)。
使用 Ramda 有很多方法可以实现这一点
想到的是
R.length([1,2]) === R.length([2,1]) && R.isEmpty(R.symmetricDifference([1,2], [2,1]))
edit:使用 R.difference
而不是 R.symmetricDifference
是行不通的,因为第一个只有 returns 中的元素不包含在第二个列表中的第一个列表。
R.difference([1,2], [2,1,3]) // -> []
您可以使用 countBy
构建一个 "profile" 数组:
countBy(identity, [1, 2]);
//=> {"1": 1, "2": 1}
countBy(identity, [2, 1]);
//=> {"1": 1, "2": 1}
然后你可以比较两个配置文件 eqBy
:
eqBy(countBy(identity), [1,2], [2,1])
//=> true
它不能那样工作的原因——除了 Ramda 函数被命名为 equals
而不是 isEqual
之外——数组是本质上有序的容器。 [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}
Ramda 不公开其内部 _Set
类型——也许应该公开——但是 it uses them in such functions as difference
, and through that in 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/ramda@0.26.1"></script><script>
const {compose, isEmpty, symmetricDifference} = ramda; </script>
但是,如果您需要测试多重性——也就是说,arr1
包含 {x: 42}
的两个副本,而 arr2
只有一个,所以它们是不同的——那么我会使用 customcommander 的答案。