Dict and str.join()

Raindrops
Raindrops in Python
def convert(number):
    sounds = {3: 'Pling', 5: 'Plang', 7: 'Plong'}

    results = ''.join(sounds[divisor] for 
                      divisor in sounds.keys()
                      if number % divisor == 0)

    return results or str(number)

This approach uses a dictionary called 'sounds' with factors as keys and sound strings as values. A generator-expression inside of str.join() loops through the dictionary view object sounds.keys(), which is a sequence of all the dictionary keys. Each value is looked up for every factor (key) where number % divisor == 0. str.join() then compiles the results.

This is the equivalent of:

def convert(number):
    sounds = {3: 'Pling', 5: 'Plang', 7: 'Plong'}
    results = []

    for divisor in sounds.keys():
        if number % divisor == 0:
            # Looks up the value by the divisor key and appends to the results list.
            results.append(sounds[divisor]) 
    
    return ''.join(results) or str(number)

The advantage of the generator expression is that no intermediary list is created in memory. This will definitely save memory, and might also be slightly faster than a "classic" loop that appends to a list.

Finally, this could all be done as a 'one liner'. But this becomes both harder to read and harder to maintain:

def convert(number):
    return ''.join(sound for divisor, sound in 
                   {3: 'Pling', 5: 'Plang', 7: 'Plong'}.items()
                   if (number % divisor == 0)) or str(number)
11th Sep 2024 · Found it useful?

Other Approaches to Raindrops in Python

Other ways our community solved this exercise
def convert(num):
    sounds = ''

    if num % 3 == 0: sounds += 'Pling'
    if num % 5 == 0: sounds += 'Plang'
    if num % 7 == 0: sounds += 'Plong'

    return sounds or str(num)
if statements

Use a series of if statements and string concatenation.

def convert(number):
    sounds = ''
    drops = ("i", 3), ("a", 5), ("o", 7)

    for vowel, factor in drops:
        if number % factor == 0:
            sounds += f'Pl{vowel}ng'
    return sounds or str(number)
Loop and f-string

Loop through a tuple and assemble output via an f-string.

def convert(number):
    drops = ["Pling","Plang","Plong"]
    factors = [3,5,7]
    sounds = ''.join(drops[index] for
                     index, factor in
                     enumerate(factors) if (number % factor == 0))

    return sounds or str(number)
Sequence(s) with str.join()

Use one or more sequences and str.join() with a generator-expression.

def convert(number):
    threes = '' if number % 3 else 'Pling'
    fives =  '' if number % 5 else 'Plang'
    sevens = '' if number % 7 else 'Plong'

    return f'{threes}{fives}{sevens}' or str(number)
Truthy and Falsey Values with f-strings

Use ternaries to build words and an f-string to assemble the result.

from itertools import compress

def convert(number):
    sounds ='Pling','Plang','Plong'
    mask =  ((number % factor) == 0 for factor in (3,5,7))
    return ''.join(compress(sounds, mask)) or str(number)
itertools.compress

Use itertools.compress() with a list mask.

from functools import reduce

def convert(number):
    sounds = ('Pling','Plang','Plong')
    factors = ((number % factor) == 0 for factor in (3,5,7))
    result = reduce(lambda sound, item : sound + (item[0] * item[1]), zip(sounds, factors), '')

    return result or str(number)
functools.reduce

Use functools.reduce() and zip().