functools.reduce

Raindrops
Raindrops in Python
from functools import reduce

def convert(number):
    sounds = ('Pling','Plang','Plong')
    factors = ((number % factor) == 0 for factor in (3,5,7)) #1 if no remainder, 0 if a remainder.
    result = reduce(lambda sound, item : sound + (item[0] * item[1]), zip(sounds, factors), '')
    
    return result or str(number)

This is essentially the same strategy as the itertools.compress() approach, but uses functools.reduce with a lambda expression and string multiplication as a kind of mask.

The factors are calculated and then zip()ed with the sounds into tuples. Each string (position 0 in the tuple) is multiplied by the 'factor' (a 1 if there is no remainder and a 0 if there is a remainder). The result is then 'reduced' to a combined result string with an empty string as an initializer. If the result is empty, the number as a string is returned instead.

This is an interesting use of functools.reduce(), but not necessarily the most readable way to solve this exercise. Importing functools adds overhead and separating the sounds from the factors risks errors as the factor list expands. The syntax of reduce() also obfuscates string creation/concatenation. Unless the team maintaining this code is comfortable with functools.reduce(), this might be better re-written using join():

def convert(number):
    sounds = ('Pling','Plang','Plong')
    factors = ((number % factor) == 0 for factor in (3,5,7))
    result = ''.join((item[0] * item[1]) for item in zip(sounds, factors))
    
    return result or str(number)
20th Nov 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.

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)
Dict and str.join()

Use a dict to hold factors:values and str.join() with a generator-expression.

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.