List 如何以函数样式从列表中添加选定行的值?

List 如何以函数样式从列表中添加选定行的值?,list,scala,functional-programming,sum,List,Scala,Functional Programming,Sum,我以命令式的方式解决了我的问题,但看起来很难看。我如何使它更好(更优雅、更简洁、更实用——最后是Scala)。应跳过值与前一行相同但字母不同的行,并添加行的所有其他值 val row1 = new Row(20, "A", true) // add value val row2 = new Row(30, "A", true) // add value val row3 = new Row(40, "A", true) // add value val row4 =

我以命令式的方式解决了我的问题,但看起来很难看。我如何使它更好(更优雅、更简洁、更实用——最后是Scala)。应跳过值与前一行相同但字母不同的行,并添加行的所有其他值

val row1 = new Row(20, "A", true)    // add value  
val row2 = new Row(30, "A", true)    // add value  
val row3 = new Row(40, "A", true)    // add value  
val row4 = new Row(40, "B", true)    // same value as the previous element & different letter -> skip row  
val row5 = new Row(60, "B", true)    // add value  
val row6 = new Row(70, "B", true)    // add value  
val row7 = new Row(70, "B", true)    // same value as the previous element, but the same letter -> add value  

val rows = List(row1, row2, row3, row4, row5, row6, row7)  

var previousLetter = " "    
var previousValue  = 0.00  
var countSkip = 0  

for (row <- rows) {  
  if (row.value == previousValue && row.letter != previousLetter) {  
      row.relevant = false  
      countSkip += 1  
  }  
  previousLetter = row.letter  
  previousValue  = row.value  
}  

// get sum  
val sumValue = rows.filter(_.relevant == true).map(_.value) reduceLeftOption(_ + _)  
val sum = sumValue match {  
    case Some(d) => d  
    case None => 0.00  
}  

assert(sum == 290)  
assert(countSkip == 1) 
val row1=新行(20,“A”,true)//添加值
val row2=新行(30,“A”,true)//添加值
val row3=新行(40,“A”,true)//添加值
val row4=新行(40,“B”,true)//与上一个元素的值相同&不同的字母->跳过行
val row5=新行(60,“B”,true)//添加值
val row6=新行(70,“B”,true)//添加值
val row7=新行(70,“B”,true)//与上一个元素的值相同,但字母相同->添加值
val rows=列表(第1行、第2行、第3行、第4行、第5行、第6行、第7行)
var previousLetter=“”
var previousValue=0.00
var countSkip=0
(d排)
案例无=>0.00
}  
断言(总和=290)
断言(countSkip==1)
提前谢谢

Twistleton减少它:

rows.reduceLeft { (prev, curr) =>
  if (prev.value == curr.value && prev.letter != curr.letter) {
    curr.relevant = false
    countSkip += 1
  }
  curr
}
折叠它:

scala> rows.foldLeft((row1, 0))((p:(Row,Int), r:Row) => (r, p._2 + (if (p._1.value == r.value && p._1.letter != r.letter) 0 else r.value)))._2

res2: Int = 290
当然,您可以删除
的布尔成员,如果您不需要它来做其他事情

我认为当行是case类时(删除布尔值)的最短(防弹)解决方案是

(rows.head :: rows).sliding(2).collect{ 
     case List(Row(v1,c1), Row(v2,c2)) if ! (v1 == v2 && c1 != c2) => v2 }.sum
(如果将数字保留在一行中,则只会多出两个字符)。如果还需要跳过该数字

val indicated = (rows zip rows.take(1) ::: rows).collect {
  case (Row(v1,c1), Row(v2,c2)) => (v1, v1 != v2 || c1 == c2)
}
val countSkip = indicated.filterNot(_._2).length
val sum = indicated.filter(_._2).map(_._1).sum

请将
.relevant==true
简化为
.relevant
!shiverIn事实上这比我的好,因为它只浏览了一次列表。但它缺乏一点可读性。遗憾的是,
(r1.value!=r2.value | r1.letter==r2.letter)*r2.value
不是有效的Scala。等等……不在我的回复中(2.8.1.final):
错误:value*不是Boolean
的成员。您的环境是什么?它也是2.8.1的final,但我用以下方式尝试它作为scala脚本:scala校验和。scalatoried它作为脚本并使用scalac:相同的错误。什么…?!啊,误解。我以为您想建议bools上存在
*
。当然,我发布的代码是啊,是的,“滑动”。我以为有什么东西能做到这一点,但我记不起它的名字了。这么多有趣的方法…是的,但我们的解决方案基本上非常相似(例如,我也必须添加头,你用它作为初始值)。collect是另一个非常好的方法,它允许同时进行过滤和映射!我甚至不知道Scala有警卫。滑动虫子已经修好了吗?还是另一个?@Rustem-我相信它是固定的,但不是在2.8.1决赛中,这是我假设人们正在使用的。
(for ((Row(v1,c1), Row(v2,c2)) <- (rows zip rows.take(1) ::: rows) if (v1 != v2 || c1 == c2)) yield v1).sum
(rows zip rows.take(1) ::: rows).collect{
  case (Row(v1,c1), Row(v2,c2)) if (v1 != v2 || c1 == c2) => v1
}.sum
val indicated = (rows zip rows.take(1) ::: rows).collect {
  case (Row(v1,c1), Row(v2,c2)) => (v1, v1 != v2 || c1 == c2)
}
val countSkip = indicated.filterNot(_._2).length
val sum = indicated.filter(_._2).map(_._1).sum