the jaccard similarity coefficient is a commonly used indicator of the similarity between two sets let u be a set and a and b be subsets of u then the jaccard indexsimilarity is defined to be the ratio of the number of elements of their intersection and the number of elements of their union inspired from wikipedia and the book mining of massive datasets mmds 2nd edition chapter 3 https en wikipedia orgwikijaccardindex https mmds org jaccard similarity is widely used with minhashing finds the jaccard similarity between two sets essentially its intersection over union the alternative way to calculate this is to take union as sum of the number of items in the two sets this will lead to jaccard similarity of a set with itself be 12 instead of 1 mmds 2nd edition page 77 parameters seta set list tuple a nonempty setlist setb set list tuple a nonempty setlist alternativeunion boolean if true use sum of number of items as union output float the jaccard similarity between the two sets examples seta a b c d e setb c d e f h i jaccardsimilarityseta setb 0 375 jaccardsimilarityseta seta 1 0 jaccardsimilarityseta seta true 0 5 seta a b c d e setb c d e f h i jaccardsimilarityseta setb 0 375 seta c d e f h i setb a b c d e jaccardsimilarityseta setb 0 375 seta c d e f h i setb a b c d jaccardsimilarityseta setb true 0 2 seta a b setb c d jaccardsimilarityseta setb traceback most recent call last valueerror set a and b must either both be sets or be either a list or a tuple cast seta to list because tuples cannot be mutated finds the jaccard similarity between two sets essentially its intersection over union the alternative way to calculate this is to take union as sum of the number of items in the two sets this will lead to jaccard similarity of a set with itself be 1 2 instead of 1 mmds 2nd edition page 77 parameters set_a set list tuple a non empty set list set_b set list tuple a non empty set list alternativeunion boolean if true use sum of number of items as union output float the jaccard similarity between the two sets examples set_a a b c d e set_b c d e f h i jaccard_similarity set_a set_b 0 375 jaccard_similarity set_a set_a 1 0 jaccard_similarity set_a set_a true 0 5 set_a a b c d e set_b c d e f h i jaccard_similarity set_a set_b 0 375 set_a c d e f h i set_b a b c d e jaccard_similarity set_a set_b 0 375 set_a c d e f h i set_b a b c d jaccard_similarity set_a set_b true 0 2 set_a a b set_b c d jaccard_similarity set_a set_b traceback most recent call last valueerror set a and b must either both be sets or be either a list or a tuple cast set_a to list because tuples cannot be mutated
def jaccard_similarity(
    set_a: set[str] | list[str] | tuple[str],
    set_b: set[str] | list[str] | tuple[str],
    alternative_union=False,
):
    

    if isinstance(set_a, set) and isinstance(set_b, set):
        intersection_length = len(set_a.intersection(set_b))

        if alternative_union:
            union_length = len(set_a) + len(set_b)
        else:
            union_length = len(set_a.union(set_b))

        return intersection_length / union_length

    elif isinstance(set_a, (list, tuple)) and isinstance(set_b, (list, tuple)):
        intersection = [element for element in set_a if element in set_b]

        if alternative_union:
            return len(intersection) / (len(set_a) + len(set_b))
        else:
            
            union = list(set_a) + [element for element in set_b if element not in set_a]
            return len(intersection) / len(union)
    raise ValueError(
        "Set a and b must either both be sets or be either a list or a tuple."
    )


if __name__ == "__main__":
    set_a = {"a", "b", "c", "d", "e"}
    set_b = {"c", "d", "e", "f", "h", "i"}
    print(jaccard_similarity(set_a, set_b))