我有一个列表,其中可能包含某些连续的相同元素。我想用一个元素替换许多连续的相同元素。如何在scala 中进行
假设我的列表是
List(5, 7, 2, 3, 3, 3, 5, 5, 3, 3, 2, 2, 2)
我想要输出列表作为
List(5, 7, 2, 3, 5, 3, 2)
使用sliding
:可以非常干净地完成
myList.head :: myList.sliding(2).collect { case Seq(a,b) if a != b => b }.toList
它会查看所有的对,对于每个不匹配的对(a,b)
,它会返回b
。但是,它必须把原来的a
放在列表的前面。
一种方法就是这样
我相信还有更好的方法。
list.tail.foldLeft(List[Int](list.head))((prev, next) => {
if (prev.last != next) prev +: next
else prev
})
foldLeft
取一个参数(在第一个应用程序中),从左到右遍历列表,将prev
和next
应用于给定的双参数函数,其中prev
是迄今为止函数的结果,next
是列表中的下一个元素。
另一种方式:
list.zipWithIndex.filter(l => (l._2 == 0) || (l._1 != list(l._2-1))).map(_._1)
通常,list.zip(otherList)
返回相应元素的元组列表。例如,List(1,2,3).zip(List(4,5,6))
将产生List((1,4), (2,5), (3,6))
。zipWithIndex
是一个特定的函数,它将每个列表元素与其索引附加在一起,从而产生一个列表,其中每个元素的形式为(original_list_element, index)
。
CCD_ 15返回仅包含为CCD_ 17返回CCD_ 16的元素的列表。我给出的函数只是检查这个元素是否等于原始列表中的前一个元素(或者索引为0)。
最后,.map(_._1)
只是删除了索引。
val myList = List(5, 7, 2, 3, 3, 3, 5, 5, 3, 3, 2, 2, 2)
myList.foldRight[List[Int]](Nil) { case (x, xs) =>
if (xs.isEmpty || xs.head != x) x :: xs else xs }
// res: List[Int] = List(5, 7, 2, 3, 5, 3, 2)
(答案从该副本中移出)
这是的一个变体
- 尾部递归
- 不使用库中的任何方法(无论好坏)
代码:
def compress[A](xs: List[A]): List[A] = {
@annotation.tailrec
def rec(rest: List[A], stack: List[A]): List[A] = {
(rest, stack) match {
case (Nil, s) => s
case (h :: t, Nil) => rec(t, List(h))
case (h :: t, a :: b) =>
if (h == a) rec(t, stack)
else rec(t, h :: stack)
}
}
rec(xs, Nil).reverse
}
示例
println(compress(List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e)))
产生以下输出:
List('a, 'b, 'c, 'a, 'd, 'e)
val l = List(5, 7,2, 3, 3, 3, 5, 5, 3, 3, 2, 2, 2)
def f(l: List[Int]): List[Int] = l match {
case Nil => Nil
case x :: y :: tail if x == y => f(y::tail)
case x :: tail => x :: f(tail)
}
println(f(l)) //List(5, 7, 2, 3, 5, 3, 2)
当然,你可以让它成为递归的尾部
import scala.collection.mutable.ListBuffer
object HelloWorld {
def main(args:Array[String]) {
val lst=List(5, 7, 2, 3, 3, 3, 5, 5, 3, 3, 2, 2, 2)
val lstBf=ListBuffer[Int](lst.head)
for(i<-0 to lst.length-2){
if(lst(i)!=lst(i+1)){
lstBf+=lst(i+1)
}
}
println(lstBf.toList)
}
}
试试这个,
val y = list.sliding(2).toList
val x =y.filter(x=> (x.head != x.tail.head)).map(_.head) :+ (y.reverse.filter(x=> x.head !=x.tail.head)).head.tail.head
另一种变体
val is = List(5, 7,2, 3, 3, 3, 5, 5, 3, 3, 2, 2, 2)
val ps = is.head::((is zip is.tail) collect { case (a,b) if a != b => b })
//> ps : List[Int] = List(5, 7, 2, 3, 5, 3, 2)
(is zip is.tail
正在执行与.sliding(2)
类似的操作)