lolveley
lolveley

Reputation: 1709

filter a list of lists : basic thing

Do you know why this program does not give expected answer (List(3,3)) ?

val l=List(List(1,2),List(3,3))
println(l.filter(_ match{
    case u::v => u==v
    case _ => false
}))

thanks!

Upvotes: 1

Views: 1396

Answers (4)

gourlaysama
gourlaysama

Reputation: 11280

If you want to extract the first two elements from your sublists and compare them, you need two :: in your case:

l.filter { 
  case u :: v :: _ => u == v
  case _ => false
}

If you want to make sure all elements of the sublists are equal, you could use forall:

l.filter {
  case h :: Nil => false // if you want to exclude single elements
  case h :: r => r.forall(_ == h)
  case _ => false
}

Upvotes: 2

Shadowlands
Shadowlands

Reputation: 15074

An alternate way of coding this, that would be useful if you might be dealing with lists of arbitrary length and want to filter down to only those lists with all elements the same, would be:

l.filter(ls => !ls.isEmpty && ls.forall(_ == ls.head))

(the !ls.isEmpty fragment presumes you would wish to exclude empty lists)

Upvotes: 2

Jatin
Jatin

Reputation: 31724

You need to check the documentation of class ::. The constructor argument it takes are (hd: B, tl: List[B])

In your case u becomes hd and v is List[In]. And doing u==v is like doing hd.equals(list) which gives wrong result.

scala> val l= List(List(1,2),List(3,3),List(1),List(1,2,3),List(4,4,4,4))
l: List[List[Int]] = List(List(1, 2), List(3, 3))

scala> l.filter(_ match{
    case u::v =>  Some(u) == v.headOption
    case _ => false
})
res8: List[List[Int]] = List(List(3, 3), List(4, 4, 4, 4))

The above is an idiomatic way of doing it.

Upvotes: 0

rarry
rarry

Reputation: 3573

case u::v => u==v

Here, u is of type Int, while v is of type List[Int]. They cannot be equal.

Upvotes: 3

Related Questions