Shakti
Shakti

Reputation: 2033

How to filter a list of tuples in scala?

I have the following list in Scala which I want to filter based on a criteria such that if there are any tuples with duplicate first value , Like from the below example I want to exclude

List((a,1), (a,2)) 

since it is having have "a" as duplicate .

Upvotes: 0

Views: 12262

Answers (4)

Jules Ivanic
Jules Ivanic

Reputation: 1617

based on the @pagoda_5b solution, I think we could find a better one.

What do you think about:

def noDuplicateKeys(l: List[(Char, Int)]): Boolean = l.toMap.size == l.size

list filter noDuplicateKeys

;)

Upvotes: 0

Brian
Brian

Reputation: 20285

I saw this as filtering out items from List[List[Tuple2[Char, Int]]] where an element of the list has the same elements. In this case an element of the list is List[Tuple2[Char, Int]] which I want to return a Boolean when the elements are the same. This List[Tuple2[Char, Int]] gets mapped to the first element of the Tuple and then logic is applied to the new list of chars using distinct and size to check if the elements are the same and to retain those that only have one element.

The filter

filter(xs => xs.map(ys => ys._1).distinct.size != 1 || xs.size == 1)

Test data:

scala> val a = List(List(('a',1)))
a: List[List[(Char, Int)]] = List(List((a,1)))

scala> val aa = List(List(('a',1),('a',1)))
aa: List[List[(Char, Int)]] = List(List((a,1), (a,1)))

scala> val ab = List(List(('a',1),('b',1)))
ab: List[List[(Char, Int)]] = List(List((a,1), (b,1)))

scala> val aba = List(List(('a',1),('b',1),('a',1)))
aba: List[List[(Char, Int)]] = List(List((a,1), (b,1), (a,1)))

Test cases.

scala> a.filter(xs => xs.map(ys => ys._1).distinct.size != 1 || xs.size == 1)
res34: List[List[(Char, Int)]] = List(List((a,1)))

scala> aa.filter(xs => xs.map(ys => ys._1).distinct.size != 1 || xs.size == 1)
res35: List[List[(Char, Int)]] = List()

scala> ab.filter(xs => xs.map(ys => ys._1).distinct.size != 1 || xs.size == 1)
res36: List[List[(Char, Int)]] = List(List((a,1), (b,1)))

scala> aba.filter(xs => xs.map(ys => ys._1).distinct.size != 1 || xs.size == 1)
res37: List[List[(Char, Int)]] = List(List((a,1), (b,1), (a,1)))

Upvotes: 1

pagoda_5b
pagoda_5b

Reputation: 7373

You want to filter your result with a function that only leaves untouched those lists with no duplicate "keys"

result filter noDuplicateKeys

This filtering function must take a list of pairs List[(A,B)] and return true only if the pair first element is not present elsewhere for all elements, and can be implemented as

def noDuplicateKeys[A, B](xs: List[(A, B)]) = 
    (xs groupBy (_._1)).values forall {_.size < 2}

It groups the elements into a Map whose keys are the As and whose values are a corresponding list of the Bs paired with that key.

From this values you can only accept those that have a size no more than 1

Upvotes: 5

wleao
wleao

Reputation: 2346

I believe that the following code will do what you want (to remove only the first pair, right?):

I'm using pattern matching to do so, if you want to filter everything, u could do a recursion over your list or do what Kyle proposed. Check this out:

val a = "a"                                      
val b = "b"                                     

var result =
    List(
      List(),
      List((a, 1), (a, 2)),
      List((a, 1), (b, 1)),
      List((a, 1), (b, 2)),
      List((a, 2), (b, 1)),
      List((a, 2), (b, 2)),
      List((b, 1), (b, 2)),
      List((a, 1), (a, 2), (b, 1)),
      List((a, 1), (a, 2), (b, 2)),
      List((a, 1), (b, 1), (b, 2)),
      List((a, 2), (b, 1), (b, 2)),
      List((a, 1), (a, 2), (b, 1), (b, 2))) 

val filteredResult = (for (list <- result)
    yield list match {
    case x :: y :: xys if (x._1 == y._1) =>  xys
    case _ => list
  }).distinct

Result:

//> List()
//| List((a,1), (b,1))
//| List((a,1), (b,2))
//| List((a,2), (b,1))
//| List((a,2), (b,2))
//| List((b,1))
//| List((b,2))
//| List((a,1), (b,1), (b,2))
//| List((a,2), (b,1), (b,2))
//| List((b,1), (b,2))

The distinct will just filter the resulting empty lists.

Cheers!

Upvotes: 1

Related Questions