Number of instances of each tag using functional programming

I am trying to create a function that returns Map<String, Int>, with the key being a specific tag and the value being the number of occurrences.

The object (simplified) from which I need to extract information:

class Note {
   List<String> tags
}

Function so far:

private fun extractTags(notes: List<Note>): Map<String, Int> {
    return notes.map { note -> note.tags }
                .groupBy { it }
                .mapValues { it.value.count() }    
}

At the moment, the compiler is giving me a return type mismatch Map<(Mutable)Set<String!>!, Int>, and I'm not sure if I am getting the desired result (since I still cannot verify this correctly).

I expect the result in the lines:

(tag1, 1)
(tag2, 4)
(tag3, 14)
...
+4
source share
3 answers

Iterable # asSequence , Java-8 stream-api . Sequence # flatMap tag Sequence, Sequence # groupingBy , :

private fun extractTags(notes: List<Note>): Map<String, Int> {
    return notes.asSequence()
                .flatMap { it.tags.asSequence() }
                .groupingBy { it }.eachCount()
}

: # flatMap # groupingBy , , Grouping#eachCount . Sequence .

+7

, , - " , ", .

, flatMap, groupingBy eachCount - , , .

, / :

private fun extractTags(notes: List<Note>): Map<String, Int> {
    return notes.flatMap { it.tags }
            .groupingBy { it }
            .eachCount()
}

, , , :

  • , .
  • .
  • , , .
  • , , . 10% , , 17% , . , . .
  • , , .

, .

+3

Here is your code modified to work. I changed mapto flatMap. I also provided a version implemented as an extension function. You did not succeed because you map>created List<List<String>>where you expected List<String>(therefore flagMap).

fun extractTags(notes: List<Note>): Map<String, Int> {
    return notes.flatMap { it.tags } // results in List<String>
            .groupBy { it } // results in Pair<String, List<String>>
            .mapValues { it.value.count() }
}

fun Iterable<Note>.extractTags(): Map<String, Int> {
    return this.flatMap { it.tags } // results in List<String>
            .groupBy { it } // results in Pair<String, List<String>>
            .mapValues { it.value.count() }
}

And here is some code to test with

import kotlin.collections.*

fun main(vararg args: String) : Unit {
    var notes = ArrayList<Note>()
    notes.add(Note(List<String>(1) { "tag1" }))
    notes.add(Note(List<String>(4) { "tag4" }))
    notes.add(Note(List<String>(14) { "tag14" }))

   for((first,second) in extractTags(notes))
       println("$first: $second")
   for((first,second) in notes.extractTags())
       println("$first: $second")
}

class Note {
    constructor(strings: List<String>) {
        tags = strings
    }
    var tags: List<String>
}
0
source

Source: https://habr.com/ru/post/1682129/


All Articles