我在foldLeft中有一个特殊的情况
scala> val nums = List(1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1)
nums: List[Int] = List(1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1)
我需要通过以2,3,4的序列号填充连续的零来获取输出
必需的输出:
List(1, 1, 2, 1, 2, 3, 1, 2, 3, 1, 2, 3, 4, 5, 1, 1)
我实际上需要将此应用于列表[(String,Int)]
来自
List(("a",1),("b",1),("b",0),("a",1),("a",0),("a",0),("d",1),("d",0),("d",0),("c",1),("c",0), ("c",0), ("c",0), ("c",0), ("d",1), ("a",1))
到必需的输出
List(("a",1),("b",1),("b",2),("a",1),("a",2),("a",3),("d",1),("d",2),("d",3),("c",1),("c",2), ("c",3), ("c",4), ("c",5), ("d",1), ("a",1))
我正在尝试在List [Int]上进行以下操作,但出现错误
scala> nums.foldLeft(List[Int]())( (m:List[Int],n:Int) => { val p = if(n==0) m.last+1 else n; m.++ List(p) })
<console>:26: error: missing argument list for method ++ in class List
Unapplied methods are only converted to functions when a function type is expected.
You can make this conversion explicit by writing `$plus$plus _` or `$plus$plus(_)(_)` instead of `$plus$plus`.
nums.foldLeft(List[Int]())( (m:List[Int],n:Int) => { val p = if(n==0) m.last+1 else n; m.++ List(p) })
^
scala>
如何解决此问题并将逻辑应用于List [(String,Int])?。
答案 0 :(得分:3)
m.++ List(p)
是无效的Scala语法。应该是m ++ List(p)
。
但是您也可以只使用运算符:+
。
示例(仅包括Int
和(String, Int)
):
val stringsAndNums = List(
("a",1),("b",1),("b",0),("a",1),("a",0),("a",0),("d",1),("d",0),("d",0),("c",1),("c",0), ("c",0), ("c",0), ("c",0), ("d",1), ("a",1)
)
// Without strings
val nums = stringsAndNums.map{case (a: String, b: Int) => b}
println(
nums.foldLeft(
List[Int]()
)(
(m: List[Int], n: Int) => {
val p = if(n == 0) m.last + 1 else n
m :+ p
}
)
)
// With strings
println(
stringsAndNums.foldLeft(
List[(String, Int)]()
)(
(m: List[(String, Int)], n: (String, Int)) => {
val p = if(n._2 == 0) (n._1, m.last._2 + 1) else n
m :+ p
}
)
)
结果:
List(1, 1, 2, 1, 2, 3, 1, 2, 3, 1, 2, 3, 4, 5, 1, 1)
List((a,1), (b,1), (b,2), (a,1), (a,2), (a,3), (d,1), (d,2), (d,3), (c,1), (c,2), (c,3), (c,4), (c,5), (d,1), (a,1))
答案 1 :(得分:3)
实际上,方法scanLeft
比foldLeft
更适合该问题。
在这里:
对于List[Int]
:
scala> val nums = List(1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1)
nums: List[Int] = List(1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1)
scala> nums.scanLeft(0){ (r, n) => if(n == 0) r + 1 else n }.tail
res1: List[Int] = List(1, 1, 2, 1, 2, 3, 1, 2, 3, 1, 2, 3, 4, 5, 1, 1)
对于List[(String Int)]
:
scala> val xs = List(("a",1),("b",1),("b",0),("a",1),("a",0),("a",0),("d",1),("d",0),("d",0),("c",1),("c",0), ("c",0), ("c",0), ("c",0), ("d",1), ("a",1))
xs: List[(String, Int)] = List((a,1), (b,1), (b,0), (a,1), (a,0), (a,0), (d,1), (d,0), (d,0), (c,1), (c,0), (c,0), (c,0), (c,0), (d,1), (a,1))
scala> xs.scanLeft(("", 0)){ case((_, r), (c, n)) => (c, if(n == 0) r+1 else n) }.tail
res2: List[(String, Int)] = List((a,1), (b,1), (b,2), (a,1), (a,2), (a,3), (d,1), (d,2), (d,3), (c,1), (c,2), (c,3), (c,4), (c,5), (d,1), (a,1))
即使第一个数字为零,此解决方案也可以使用,@ Markus Appel的解决方案在这种情况下不起作用。
答案 2 :(得分:2)
请注意,由于嵌套调用slow
(列表中的O(n^2)
),.last
版本为O(n)
。
def slow(list: List[(String, Int)]): List[(String, Int)] =
list.foldLeft(List[(String, Int)]()) {
(m: List[(String, Int)], n: (String, Int)) => {
val p = if (n._2 == 0) (n._1, m.last._2 + 1) else n
m :+ p
}
}
您可以通过将列表附加到头部并在最后将其反转来构建O(n)
解决方案:
def fast(list: List[(String, Int)]): List[(String, Int)] =
list.foldLeft(List[(String, Int)]()) {
(m: List[(String, Int)], n: (String, Int)) => {
val p = if (n._2 == 0) (n._1, m.head._2 + 1) else n
p +: m
}
}.reverse
在我的计算机上,对于32000大小的列表,快速变体需要18毫秒,而慢速变体需要6秒。