kundan kanan
kundan kanan

Reputation: 91

Remove consecutive identical elements in scala

I have a list which may contain certain consecutive identical elements.I want to replace many consecutive identical elements with one. How to do it in scala

Lets say my list is

List(5, 7, 2, 3, 3, 3, 5, 5, 3, 3, 2, 2, 2)

I want output list as

List(5, 7, 2, 3, 5, 3, 2)

Upvotes: 9

Views: 3327

Answers (8)

dexjq23
dexjq23

Reputation: 386

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)

Upvotes: 4

The Archetypal Paul
The Archetypal Paul

Reputation: 41769

Yet another variant

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)

(the is zip is.tail is doing something similar to .sliding(2))

Upvotes: 0

Gaurav Gupta
Gaurav Gupta

Reputation: 159

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)
}

}

Upvotes: 1

Andrey Tyukin
Andrey Tyukin

Reputation: 44957

(answer moved from this duplicate)

Here is a variant that is

  • tail-recursive
  • does not use any methods from the library (for better or worse)

Code:

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
}

Example

println(compress(List('a, 'a, 'a, 'a, 'b, 'c, 'c, 'a, 'a, 'd, 'e, 'e, 'e, 'e)))

produces the following output:

List('a, 'b, 'c, 'a, 'd, 'e)

Upvotes: 2

S.Karthik
S.Karthik

Reputation: 1389

Try this,

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

Upvotes: 0

Marek Adamek
Marek Adamek

Reputation: 520

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)

Of course you can make it tail recursive

Upvotes: 1

dhg
dhg

Reputation: 52691

It can be done pretty cleanly using sliding:

myList.head :: myList.sliding(2).collect { case Seq(a,b) if a != b => b }.toList

It looks at all the pairs, and for every non-matching pair (a,b), it gives you back b. But then it has to stick the original a on the front of the list.

Upvotes: 7

Ritwik Bose
Ritwik Bose

Reputation: 6069

One way is this.

I'm sure there is a better way.

list.tail.foldLeft(List[Int](list.head))((prev, next) => {
  if (prev.last != next) prev +: next
  else prev
})

foldLeft takes a parameter (in the first application) and goes from left to right through your list, applying prev and next to the two parameter function it is given, where prev is the result of the function so far and next is the next element in your list.

another way:

list.zipWithIndex.filter(l => (l._2 == 0) || (l._1 != list(l._2-1))).map(_._1)

In general, list.zip(otherList) returns a list of tuples of corresponding elements. For example List(1,2,3).zip(List(4,5,6)) will result in List((1,4), (2,5), (3,6)). zipWithIndex is a specific function which attaches each list element with its index, resulting in a list where each element is of the form (original_list_element, index).

list.filter(function_returning_boolean) returns a list with only the elements that returned true for function_returning_boolean. The function I gave simply checks if this element is equal to the previous in the original list (or the index is 0).

The last part, .map(_._1) just removes the indices.

Upvotes: 4

Related Questions