Reputation:
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
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
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
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