Reputation: 2033
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
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
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
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 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
Upvotes: 5
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