提问人:dev 提问时间:9/30/2020 最后编辑:dev 更新时间:11/24/2022 访问量:2046
Scala:比较数组忽略顺序
Scala: Compare Arrays ignoring order
问:
我想知道数组中是否有任何方法可以检查忽略顺序的相等性。到目前为止,我确实找到了这个:
test("test ignoring order"){
assert(Array(1,2,4,5).sameElements(Array(1,4,2,5)))
}
但它失败了,因为顺序不同:
org.scalatest.exceptions.TestFailedException: scala.Predef.intArrayOps(scala.Array.apply(1, 2, 4, 5)).sameElements[Int](scala.Predef.wrapIntArray(scala.Array.apply(1, 4, 2, 5))) was false
有没有办法做到这一点,在数组内部或外部?
编辑:我不需要对数组进行排序,我只想比较它们而忽略顺序。
答:
1赞
lprakashv
10/1/2020
#1
下面将对两个数组进行排序,然后将它们相等:
test("test ignoring order"){
assert(Array(1,2,4,5).sorted sameElements Array(1,4,2,5).sorted)
}
笔记:
- 如果您正在处理除 . 之外的其他一些集合,则可以使用 instead 代替。
==
sameElements
Array
array1.toSet == array2.toSet
如果其中一个数组有重复项而另一个数组没有,则不起作用。
评论
0赞
dev
10/1/2020
感谢您的回答,但不幸的是,我想忽略顺序来比较它们,而不对它们进行排序
4赞
Tim
10/1/2020
@dev 对它们进行排序有什么问题?这是一个测试,而不是主线代码。
1赞
Maestro
10/1/2020
#2
这是否按预期工作?
import scala.annotation.tailrec
def equalsIgnoringOrder(first:Array[Int], second:Array[Int]) : Boolean = {
def removeAtIndex(i:Int, array: Array[Int]) : Array[Int] = {
val buffer = array.toBuffer
buffer.remove(i)
buffer.toArray
}
@tailrec
def firstEqualSecondRec(i:Int, other:Array[Int]) : Boolean = {
if(other.isEmpty) true
else {
val el = first(i)
val index = other.indexOf(el)
if(index == -1) false
else firstEqualSecondRec(i+1, removeAtIndex(index, other))
}
}
if (first.length != second.length) false
else {
val startingIndex = 0
firstEqualSecondRec(startingIndex, second)
}
}
2赞
jwvh
10/2/2020
#3
一个简单的递归就可以了。
def isSame[T](arrA:Array[T], arrB:Array[T]) :Boolean =
arrA.length == arrB.length &&
(arrA.isEmpty || isSame(arrA.filterNot(_ == arrA.head)
,arrB.filterNot(_ == arrA.head)))
但@Tim的问题是有道理的:你对明显而简单的排序解决方案有什么反对意见?
评论
1赞
Tim
10/2/2020
好。可以避免裸露head
arrA.length == arrB.length && arrA.headOption.forall(x => isSame(arrA.filterNot(_ == x), arrB.filterNot(_ == x)))
0赞
jwvh
10/2/2020
@Tim;我喜欢。我们放弃了尾递归,但这是一件小事。
0赞
Tim
10/2/2020
关于尾递归的好点。归根结底,这取决于这样做的动机是什么,目前尚不清楚。
3赞
Joshua Esolk
11/24/2022
#4
这是一个较旧的线程,但我只是有同样的问题。
建议的答案包括排序(仅适用于可比较的对象)或具有 O(n^2) 运行时行为(和/或非平凡递归)的方法。
另一种(简单但易于理解且功能强大)方法是使用 Scala 的 diff 函数:
def hasSameElementsUnordered[T](arrA: Array[T], arrB: Array[T]): Boolean = {
(arrA.length == arrB.length) && (arrA diff arrB).isEmpty
}
顺便说一句,这适用于任何集合和元素类型,而不仅仅是数组和可比较对象。 在内部,diff() 构建了一个出现次数哈希映射,因此对于较大的集合,运行时行为会好得多。
评论
Array(1,2,4,5) contain theSameElementsAs Array(1,2,4,5)
sort
groupMapReduce(identity)(_ => 1)(_ + _)