user4210777
user4210777

Reputation:

Filter function in Scala not working

   def filter(data : List[Int]) : List[Int] = {


  if(data.length == 0){
  return data;

  }else{
    var list: List[Int] = List();
    var index = 0;

    for((value,index) <- data.zipWithIndex){
        if(list(index) == list(index+1){
                list = value :: list;
                //println(list(index));
        }
    }




  }

    return list

  }
}

Im having trouble with my function. 'data' is an array of ints and this function needs to filter all duplicates that are next to each other. For example {1,2,3,3,4,3,1} would be filters to {1,2,3,4,3,1}. This function is currently throwing array out of bounds exceptions. My knowledge in scala is very limited so please keep all answers simple due to the lack of knowledge. Thanks for all help provided :D.

Upvotes: 0

Views: 920

Answers (3)

S.Karthik
S.Karthik

Reputation: 1389

Try this,

  val list = List(1, 2, 3, 3, 4, 3, 1,1,5,5,6,6)  
  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

Brian
Brian

Reputation: 20295

Accessing a list via an index and creating another list for results is kind of a code smell. Here's another approach with recursion and pattern matching which makes for a rather simple solution.

def filterNextTo(xs: List[Int]):List[Int] = xs match{
  case h :: ht :: t => if(h == ht) filterNextTo(xs.tail) else h :: filterNextTo(xs.tail)
  case h :: Nil => List(h)
  case Nil => Nil
}

Test case:

scala> xs
res7: List[Int] = List(1, 2, 3, 3, 4, 3, 1)

scala> filterNextTo(xs)
res8: List[Int] = List(1, 2, 3, 4, 3, 1)

This can also be done with zip, filter, and map but requires a bit of tuple wrangling and handling a special case which I think is less elegant.

Updated to add a tail recursive version per @Paul's comment:

def filterNextTo(xs: List[Int]) = {
  @tailrec
  def filterNextToR(xs: List[Int], acc: List[Int]): List[Int] = xs match{
    case h :: ht :: t if (h == ht) => filterNextToR(xs.tail, acc)
    case h :: ht :: t if (h != ht) => filterNextToR(xs.tail, h :: acc)
    case h :: t  => (h :: acc).reverse
  }
  filterNextToR(xs, List[Int]())
}

Upvotes: 1

The Archetypal Paul
The Archetypal Paul

Reputation: 41779

I think a fold is neater than the explicit recursion, and will work on long lists:

ls match {
    case Nil => Nil
    case h :: t => t.foldLeft(List(h))
                             ((a, b) => if (a.head == b) a 
                                         else b :: a)
                              .reverse
  }    
//> res0: List[Int] = List(1, 2, 3, 4, 3, 1)

Upvotes: 1

Related Questions