List 如何以函数样式从列表中添加选定行的值?
我以命令式的方式解决了我的问题,但看起来很难看。我如何使它更好(更优雅、更简洁、更实用——最后是Scala)。应跳过值与前一行相同但字母不同的行,并添加行的所有其他值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 =
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