简体   繁体   中英

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 .

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 A s and whose values are a corresponding list of the B s paired with that key.

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

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!

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

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

;)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM