pythonlist-comprehensiondictionary-comprehensionset-comprehension

Function with generic comprehension return type depending on input argument?


Assuming I have a function that converts a character in a collection of strings like -

from typing import Collection

def replace_in_collection(input_collection: Collection[str]) -> Collection[str]:
    return [x.replace('a', 'b') for x in input_collection]

How do I create this function in a generic way, So that it returns the same collection type like the input type (not just a list like in the function example above).

So what I want is something that has the following behavior:

my_set = {'ab','ac'}
my_set_result = replace_in_collection(my_set)
type(my_set_result ) # --> set

my_list = ['ab','ac']
my_list_result = replace_in_collection(my_list)
type(my_list_result) # --> list

Is there a way to create this with a comprehension without using individual type checking?


Solution

  • Assuming that all the types of collections accept iterable as __init__ parameter, that should work:

    def replace_in_collection(input_collection):
        collection_type = type(input_collection)
        return collection_type(x.replace('a', 'b') for x in input_collection)
    

    It does work for set, list and tuple.

    And as Chris Rands noted, you should probably check if your input is of supported type:

    if not isinstance(input_collection, (set, list, tuple)): # add other types if needed
        raise TypeError(f"input_collection must be of type set, list or tuple, not {type(input_collection).__name__}")