Ramda:检查两个数组是否相等

J. *_*ers 4 javascript functional-programming ramda.js

我仍在学习JavaScript中的函数式编程,并且喜欢使用Ramda。

我有两个数组。我想检查它们是否具有相同的值,而与顺序无关。我以为可以做到这一点equals。但是显然

R.equals([1, 2], [2, 1]) // false
Run Code Online (Sandbox Code Playgroud)

有没有一种有效的方法来检查两个数组是否相等?我的数组由对象组成,如果1 <X <10很重要,则最多可以容纳X * 10E4值。

Sco*_*yet 7

它之所以不能这样工作的原因-除了名称是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
Run Code Online (Sandbox Code Playgroud)

因为在这种情况下,由于长度检查会失败:

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}
Run Code Online (Sandbox Code Playgroud)

Ramda并未公开其内部_Set类型(也许应该公开),但是它在诸如difference和通过in中的函数中使用了它们symmetricDifference。这些是测试有问题的值相等的值的适当函数。

因此,我的答案将与错误的答案相似,但我的说法略有不同:

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
Run Code Online (Sandbox Code Playgroud)
<script src="https://bundle.run/ramda@0.26.1"></script><script>
const {compose, isEmpty, symmetricDifference} = ramda;   </script>
Run Code Online (Sandbox Code Playgroud)

但是,如果您需要测试多重性-也就是说,arr1包含两个副本,{x: 42}而arr2只有一个副本,则它们是不同的-那么我将使用customcommander的答案。

  • _数组是本质上有序的容器_这种直觉对于像Javascript这样的非类型化语言的类型来说在SO上很少见。不过,那只是我的主观看法。+1 (3认同)

cus*_*der 6

我会用eqBy同countBy:

您可以使用countBy来构建阵列的“配置文件”:

countBy(identity, [1, 2]);
//=> {"1": 1, "2": 1}

countBy(identity, [2, 1]);
//=> {"1": 1, "2": 1}
Run Code Online (Sandbox Code Playgroud)

然后,您可以将两个配置文件与eqBy以下内容进行比较:

eqBy(countBy(identity), [1,2], [2,1])
//=> true
Run Code Online (Sandbox Code Playgroud)