根据功能条件在其项上重新排列字典 [英] Rearranging a dictionary based on a function-condition over its items

查看:66
本文介绍了根据功能条件在其项上重新排列字典的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(关于我几天前提出的问题)

(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},"c":{2,5,4},"d":{8,11,10,18},"e":{0,3,2}}

我想有一个过程,该过程将键的值满足外部函数中给定的特定通用条件的键连接在一起.因此,新项目将具有两个键的并集作为键(顺序并不重要).该值将由条件iterf确定.

I would like to have a procedure that joins the keys whose values satisfy a certain generic condition given in an external function. The new item will therefore have as a key the union of both keys (the order is not important). The value will be determined by the condition itserf.

例如:给定此条件函数:

For example: given this condition function:

def condition(kv1: tuple, kv2: tuple):
  key1, val1 = kv1
  key2, val2 = kv2

  union = val1 | val2 #just needed for the following line
  maxDif = max(union) - min(union)

  newVal = set()
  for i in range(maxDif):
    auxVal1 = {pos - i for pos in val2}
    auxVal2 = {pos + i for pos in val2}
    intersection1 = val1.intersection(auxVal1)
    intersection2 = val1.intersection(auxVal2)
    print(intersection1, intersection2)
    if (len(intersection1) >= 3):
      newVal.update(intersection1)
    if (len(intersection2) >= 3):
      newVal.update({pos - i for pos in intersection2})

  if len(newVal)==0:
    return False
  else:
    newKey = "".join(sorted(key1+key2))
    return newKey, newVal

也就是说,令人满意的项目对在它们的值中至少有3个数字,它们之间的距离相同(差).如前所述,如果满意,那么生成的密钥就是两个密钥的并集.对于此特定示例,该值是原始值集中的(最小)匹配数字.

That is, the satisfying pair of items have at least 3 numbers in their values at the same distance (difference) between them. As said, if satisfied, the resulting key is the union of the two keys. And for this particular example, the value is the (minimum) matching numbers in the original value sets.

如何将这样的函数巧妙地应用于像 db 这样的字典?给定上述字典,预期结果将是:

How can I smartly apply a function like this to a dictionary like db? Given the aforementioned dictionary, the expected result would be:

result = {ab":{1,2,3}, cde":{0,3,2}, d":{18}}

推荐答案

您的条件";在这种情况下,不仅仅是一个条件.它实际上是合并规则,用于标识要保留的值和要丢弃的值.这可能会或可能不会允许采用通用方法,具体取决于模式和合并规则的变化方式.

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.

鉴于此,每个合并操作都可能将值保留在原始键中,而这些原始键可能会与某些其余键合并.也可以发生多个合并(例如,键"cde").从理论上讲,合并过程将需要覆盖可能不切实际的所有键的功能集.或者,可以通过使用(原始和/或合并的)密钥对进行连续精炼来执行此操作.

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.

合并条件/功能:

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 met
def merge(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 if any(a+d in B for d in delta)}
    remove    = {b for b in B if any(b-d in A for d in delta)}
    if len(keep)>=minMatch: return keep,remove
    return None,None
    
    
print( merge(db["a"],db["b"]) )  # ({1, 2, 3}, {5, 6, 7})
print( merge(db["e"],db["d"]) )  # ({0, 2, 3}, {8, 10, 11})   

合并过程:

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

这篇关于根据功能条件在其项上重新排列字典的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆