Search code examples
pythonlisttuplesoperatorssubtraction

Elegant way to find mutually exclusive tuples in the list based on the element present in each tuple


I want to subtract the two following tuples from each other to get the desired result (also included below). Note that the subtraction is based on only the a of the (a, b).

# the two tuples
first = [(('the',), 431), (('and',), 367)]
second = [(('the',), 100), (('hello',), 100)]

# the desired result
first = [(('and',), 367)]
second = [(('hello',), 100)]

I tried map(operation.sub, first, second), didn't work. Tried b = map(sub, first, second), didn't work. Says unsupported operand type(s) for -: 'tuple' and 'tuple.

Thanks for your help and time in advance.

Edit: A solution that would help me most would include creating an intersection of the two tuples and subtracting that from each of the tuples.

Edit: I want to subtract based on common items. Hope that clarifies it.


Solution

  • Maybe follow is what you want:

    # the two tuples
    first = [(('the',), 431), (('and',), 367)]
    second = [(('the',), 100), (('hello',), 100)]
    
    first_keys = set(_[0][0] for _ in first)
    second_keys = set(_[0][0] for _ in second)
    
    first = [_ for _ in first if _[0][0] not in second_keys]
    second = [_ for _ in second if _[0][0] not in first_keys]
    

    multi = [
        [(('the',), 431), (('and',), 367)],
        [(('the',), 100), (('hello',), 100)]
    ]
    
    def get_key(x):
        return x[0][0]
    
    def occur_counts(set_x):
        cnt = {}
        for x in set_x:
            cnt[get_key(x)] = cnt.get(get_key(x), 0) + 1
        return cnt
    
    
    def do_one(single, total_cnt):
        single_cnt = occur_counts(single)
        return [_ for _ in single if single_cnt[get_key(_)] == total_cnt[get_key(_)]]
    
    
    total_cnt = occur_counts(sum(multi, []))
    
    answer = [do_one(_, total_cnt) for _ in multi]