Scala 附带了很好的 corresponds
方法:
val a = scala.io.Source.fromFile("fileA").getLines().toSeq()
val b = scala.io.Source.fromFile("fileB").getLines().toSeq()
val areEqual = a.corresponds(b){_.equals(_)}
if(areEqual) ...
我很喜欢这种简洁。
是否已经定义了类似的方法,该方法也会向我报告两个序列不同的第一个位置?
即有没有更惯用的方式来编写这样的内容:
val result = ((seqA zip seqB).zipWithIndex).find{case ((a,b),i) => !a.equals(b)} match{
case Some(((a,b),i)) => s"seqA and seqB differ in pos $i: $a <> $b"
case _ => "no difference"
}
因为正如你所看到的,读起来真是让人头疼。如果我想使用三元组而不是元组的元组,情况会变得更糟:
val result = (((seqA zip seqB).zipWithIndex) map {case (t,i) => (t._1,t._2,i)}).find{case (a,b,i) => !a.equals(b)} match{
case Some((a,b,i)) => s"seqA and seqB differ in pos $i: $a <> $b"
case _ => "no difference"
}
我知道 diff
方法。不幸的是,它忽略了元素的顺序。
最佳答案
您可以使用 indexWhere
(请参阅 ScalaDoc ),如下所示:
(as zip bs).indexWhere{case (x,y) => x != y}
示例:
scala> val as = List(1,2,3,4)
scala> val bs = List(1,2,4,4)
scala> (as zip bs).indexWhere{case (x,y) => x != y}
res0: Int = 2
但是,请注意,如果一个 Seq 比另一个 Seq 长(zip
截断较长的 Seq),则所有基于 zip
的解决方案可能不会报告任何差异 - 这可能或可能不是你所需要的...
更新:对于相等长度的Seq,不同的方法如下:
as.indices.find(i => as(i) != bs(i))
这很好,因为它返回一个 Option[Int]
,因此如果 Seq 之间没有差异,它会返回 None
而不是神奇的 -1。
如果 as
比 bs
短,它的行为与其他解决方案相同,但如果 as
更长,则失败(您可以采取当然是最小长度)。
但是,由于它通过索引寻址两个 Seq,因此它仅对 IndexedSeq
表现良好。
更新2:我们可以通过使用lift
来处理不同的Seq长度,这样我们在通过索引检索元素时会得到一个Option:
bs.indices.find(i => as.lift(i) != bs.lift(i))
所以如果 as = [1,2]
和 bs = [1,2,3]
,它们不同的第一个索引是 2(因为这个元素as
中缺失)。然而,在这种情况下,我们需要对最长的 Seq 而不是最短的 Seq 调用 indices
- 或者使用 max
显式检查哪个是最长的,例如
(0 until (as.length max bs.length)).find(i => as.lift(i) != bs.lift(i))
关于Scala - 查找两个 Seq 不同的第一个位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30513297/