FizzBuzz, part 2: A fancier way

Piggybacking off my earlier post, because I have an obsessive personality I couldn't help thinking of fancier, if more convoluted, ways to write FizzBuzz. I didn't like the fact that I had to write the modulo operation and "Fizz" and "Buzz" more than once each. I came up with many variations of the code below (once again, in Kotlin):

val map = mapOf(3 to "Fizz", 5 to "Buzz")

fun main() {
    for (i in 1..100) {
        val fb = StringBuilder()
        map.forEach { if (i % it.key == 0) fb.append(it.value) }
        println(if (fb.isEmpty()) i else fb)

Here the code uses a map (a set of key-value pairs) to establish the required relationships: 3 to Fizz, and 5 to Buzz. The outer loop, counting 1 through 100, is the same as before. We initialize an empty StringBuilder, and then start a second, inner loop that goes through each of the two aforementioned key-value pairs in the map and checks it against the current number i. If the operation returns true (that is, i is a multiple of the key of the current pair in the map), the value of the pair is added to the StringBuilder. So, if the operation returns true for the first key-value pair, we get "Fizz." If only the second, "Buzz." If both times, we get "FizzBuzz." And each of these words appear in the code only once. Finally, we check if the string is empty in the end, and if so we just print the current number.

I could just as easily have done string concatenation by first assigning an empty string to a mutable variable (var fb = ""), but for reasons I don't yet entirely understand, StringBuilder performs better, especially when loops are involved. In a program this small though, nobody will notice... I think?

Another beauty of this approach is that if we wanted to, we can change the rules very easily. We can add a third key-value pair to the map, maybe 7 to "Fuzz," or use a different map entirely without rewriting anything else. Okay, I'm done with FizzBuzz now, moving on.