Skip to content Skip to sidebar Skip to footer

Rearranging A Dictionary Based On A Function-condition Over Its Items

(In relation to this question I posed a few days ago) I have a dictionary whose keys are strings, and whose values are sets of integers, for example: db = {'a':{1,2,3}, 'b':{5,6,7}

Solution 1:

Your "condition" in this case is more than just a mere condition. It is actually merging rule that identifies values to keep and values to drop. This may or may not allow a generalized approach depending on how the patterns and merge rules vary.

Given this, each merge operation could leave values in the original keys that may be merged with some of the remaining keys. Multiple merges can also occur (e.g. key "cde"). In theory the merging process would need to cover a power set of all keys which may be impractical. Alternatively, this can be performed by successive refinements using pairings of (original and/or merged) keys.

The merge condition/function:

db = {"a":{1,2,3}, "b":{5,6,7}, "c":{2,5,4}, "d":{8,11,10,18}, "e":{0,3,2}}

from itertools import product
from collections import Counter

# Apply condition and return a keep-set and a remove-set# the keep-set will be empty if the matching condition is not metdefmerge(A,B,inverted=False):
    minMatch = 3
    distances = Counter(b-a for a,b in product(A,B) if b>=a)
    delta     = [d for d,count in distances.items() if count>=minMatch]
    keep      = {a for a in A ifany(a+d in B for d in delta)}
    remove    = {b for b in B ifany(b-d in A for d in delta)}
    iflen(keep)>=minMatch: return keep,remove
    returnNone,Noneprint( merge(db["a"],db["b"]) )  # ({1, 2, 3}, {5, 6, 7})print( merge(db["e"],db["d"]) )  # ({0, 2, 3}, {8, 10, 11})   

Merge Process:

# combine dictionary keys using a merging function/conditiondefcombine(D,mergeFunction):
    result  = { k:set(v) for k,v in D.items() }  # start with copy of input
    merging = Truewhile merging:    # keep merging until no more merges are performed
        merging = Falsefor a,b in product(*2*[list(result.keys())]): # all key pairsif a==b: continueif a notin result or b notin result: continue# keys still there?
            m,n = mergeFunction(result[a],result[b])        # call merge functionifnot m : continue# if merged ...
            mergedKey = "".join(sorted(set(a+b)))             # combine keys
            result[mergedKey] = m                             # add merged setif mergedKey != a: result[a] -= m; merging = True# clean/clearifnot result[a]: del result[a]                   # original sets,if mergedKey != b: result[b] -= n; merging = True# do more mergesifnot result[b]: del result[b]
    return result

Post a Comment for "Rearranging A Dictionary Based On A Function-condition Over Its Items"