Scala - 找到两个Seq不同的第一个位置

Use*_*291 3 diff scala sequence seq

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

我非常喜欢这种简洁.

是否已经定义了类似的方法,它还会向我报告两个序列不同的第一个位置?

即,有一种更惯用的方式来写这样的东西:

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

因为你可以看到,这是颈部的血腥疼痛.如果我想使用三元组而不是元组元组,它会变得更糟:

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

我知道这个diff方法.不幸的是,那个人忽视了元素的顺序.

DNA*_*DNA 8

您可以使用indexWhere(请参阅ScalaDoc),如下所示:

(as zip bs).indexWhere{case (x,y) => x != y}
Run Code Online (Sandbox Code Playgroud)

例:

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

但是,请注意,zip如果一个Seq比另一个zip更长(截断更长的Seq),所有基于的解决方案可能都没有报告差异- 这可能是您可能需要的,也可能不是您需要的......

更新:对于长度相等的Seqs,不同的方法如下:

as.indices.find(i => as(i) != bs(i))
Run Code Online (Sandbox Code Playgroud)

这很好,因为它返回一个Option[Int],所以None如果Seqs之间没有差异,它返回而不是一个神奇的-1.

如果as比较短bs,则其行为与其他解决方案相同,但如果as更长则失败(当然,您可以采用最小长度).

但是,因为它通过索引解决了两个Seqs,所以它只能很好地用于IndexedSeqs.

更新2:我们可以通过使用来处理不同的Seq长度lift,以便在按索引检索元素时获得选项:

bs.indices.find(i => as.lift(i) != bs.lift(i))
Run Code Online (Sandbox Code Playgroud)

所以如果as = [1,2]bs = [1,2,3],它们不同的第一个索引是2(因为缺少这个元素as).但是,在这种情况下,我们需要调用indices最长的Seq而不是最短的 - 或明确检查使用最长的Seq max,例如

(0 until (as.length max bs.length)).find(i => as.lift(i) != bs.lift(i))
Run Code Online (Sandbox Code Playgroud)