Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Lists: Idiomatic way of filtering similar elements

Tags:

list

kotlin

I am searching for the opposite of distinct.

In a list with [ "a", "a", "b", "c", "b", "d" ] I only want to keep "a" and "b" because they appear multiple times.

A solution for this could be the following:

val similarsList = mutableListOf<String>()
list.filter { 
    if (similars.contains(it))
        return@filter true
    similars.add(it)
    false
}.distinct()

This will remove every element that matches an already contained element before it. In the list object all elements appearing multiple times will be stored after filter. distinct in this case cleans elements that appeared three or more times.

I am searching for an idiomatic way of doing exactly that, the opposite of distinct.

like image 266
creativecreatorormaybenot Avatar asked Mar 13 '18 08:03

creativecreatorormaybenot


2 Answers

A small improvement to the solution provided by @gil.fernandes can be made by using the API introduced in the Kotlin 1.1 standard library: .groupingBy { ... }. Instead of creating the groups right away, it creates a lazy Grouping, which can then be queried. In particular, we can ask it for .eachCount(), which returns Map<T, Int>:

val l = listOf("a", "a", "b", "c", "b", "d")

val result = l.groupingBy { it }.eachCount().filterValues { it > 1 }.keys

It is a little bit more efficient than using .groupBy { ... }, because it does not store the groups in the lists.

like image 110
hotkey Avatar answered Nov 07 '22 07:11

hotkey


If you want to filter out duplicates (non distinct items) you could try:

fun main(args: Array<String>) {
    val l = listOf( "a", "a", "b", "c", "b", "d" )
    println(l.groupBy { it }.filter { it.value.size > 1 }.keys)
}

This prints out:

[a, b]

Explanation: l.groupBy { it } produces a grouped map with this content:

{a=[a, a], b=[b, b], c=[c], d=[d]}

Then a filter is applied to this map, filtering by the values (which are lists) with a length superior to 1: filter { it.value.size > 1 }.

Finally the keys are extracted with keys.

like image 26
gil.fernandes Avatar answered Nov 07 '22 07:11

gil.fernandes