Scala转换点数组的方法

时间:2015-06-08 18:45:30

标签: scala

我有一系列积分。对于除第一点以外的每一点,我想减去前一点:

Array((1,1), (3,1), (4,3))变为Array((1,1), (2,0), (1,2))

我想出了一种“某种”功能风格:

val trans = for (i <- 0 until points.length - 1) 
  yield {
    (points(i + 1)._1 - points(i)._1, points(i + 1)._2 - points(i)._2)
}
val result = trans ++ points

但我觉得可以做得更好。完成转换后,我将要在result中添加所有元组。

5 个答案:

答案 0 :(得分:4)

通常,你写的for-comprehension是通过zip完成的:

(xs zip xs.drop(1)).map{ case ((x1,y1), (x2,y2)) => (x2-x1, y2-y1) }

其余的(添加第一个元素)是特殊目的,你可以自己做很多事情。 (您可以将(0,0)添加到xs.drop(1)的前面,或将xs.take(1)添加到结果中。)

另外,请注意,完全可以将整个算法用sum作为单个折叠或递归来编写。

(我假设你在这里没有表现限制。)

答案 1 :(得分:4)

考虑

type Point = (Int,Int)

def sub( p1: Point, p2: Point ) = (p1._1 - p2._1, p1._2 - p2._2)

等等

val points = Array((1,1), (3,1), (4,3))

for ((p1, p2) <- points.zip(points.drop(1)) yield sub(p2,p1)

答案 2 :(得分:0)

sliding还有Array方法:

(Iterator(xs(0)) ++
  xs.sliding(2)
    .map { case Array((x1, y1), (x2, y2)) =>
             (x2 - x1, y2 - y1) }).toArray
//> res0: Array[(Int, Int)] = Array((1,1), (2,0), (1,2))

答案 3 :(得分:0)

这是一个执行此操作的功能:

type Pairs = Array[(Int,Int)]
def diff(seq: Pairs): Pairs = Array(seq.head) ++ seq.sliding(2).map{case Array((a1,b1),(a2,b2)) => (a2-a1, b2-b1)}

您可以在REPL中使用它:

scala> diff(Array((1,1), (3,1), (4,3)))
res1: Array[(Int, Int)] = Array((1,1), (2,0), (1,2))

答案 4 :(得分:0)

我的解决方案非常接近榆树。 。 。但我担心他的那个实际上是马车,因为它是A)在屈服之前缺少一个括号而B)正在跳过第一个元素。所以他的结果是Array((2,0), (1,2))。可悲的是,我不能评论他的解决方案,因为我没有足够的声誉。所以这是我的解决方案:

implicit class PointUtils( val point:(Int, Int) ) extends AnyVal {
  def subtract(other:(Int, Int)) = ( point._1 - other._1, point._2 - other._2 )
}

val points = Array((1,1), (3,1), (4,3))

for( (p1, p2) <- points.zip( (0,0) +: points ) ) yield p1.subtract( p2 )

//alternatively
points.zip( (0,0) +: points ).map( t => t._1.subtract(t._2) )

我对隐式课程略有偏好,但很多人会认为榆树def sub(...)更容易理解。

另请注意,我的版本比elms使用更多内存,因为(0,0) +: points需要复制points数组,其中points.drop(1)没有。当您使用列表时,内存命中会消失。