如何使用scala链接自定义逻辑?

时间:2018-03-05 12:24:48

标签: scala scala-collections

我正在尝试使用scala

来实现多边形面积的计算

多边形区域参考https://www.mathopenref.com/coordpolygonarea.html

我能够成功编写代码但我的要求是我希望将最后一个for循环链接到点变量中,就像其他地图逻辑一样。地图不起作用,因为列表的输出是(N-1)

var lines=io.Source.stdin.getLines()
val nPoints= lines.next.toInt
var s=0
var points = lines.take(nPoints).toList map(_.split(" ")) map{case Array(e1,e2)=>(e1.toInt,e2.toInt)} 

 for(i <- 0 until points.length-1){    // want this for loop to be chained within points variable        
      s=s+(points(i)._1 * points(i+1)._2) - (points(i)._2 * points(i+1)._1)
    }



println(scala.math.abs(s/2.0))

2 个答案:

答案 0 :(得分:1)

我认为您正在寻找slidingfoldLeftsliding(2)会为您提供List(i, i+1), List(i+1, i+2),...列表,然后您可以使用foldLeft进行计算:

val s = points.sliding(2).foldLeft(0){ 
  case (acc, (p1, p2)::(q1, q2)::Nil) => acc + p1*q2 - p2*q1 } 

如果我正确阅读了公式,那么还有一个额外的术语来自第一个和最后一个顶点(顺便说一句,它看起来像你的实现中缺少的那样)。您可以单独添加,也可以重复列表末尾的第一个顶点。因此,组合到定义points的同一行并不容易。在任何情况下,我认为它更具可读性,分为单独的语句 - 一个定义points,另一个重复列表末尾的points的第一个元素,然后折叠。

编辑修复了你的点数而不是列表的元组。我相信,我也默认假设points是一个清单。

答案 1 :(得分:0)

如何(未经测试)

val points2 = points.tail :+ points.head // shift list one to the left
val area = ((points zip points2)
    .map{case (p1, p2) => (p1._1 * p2._2) - (p2._1 * p1._2)}
    .fold(0)(_+_))/2