简体   繁体   English

如何在python中动态组合集合

[英]How can I dynamically combine sets in python

I have a list of dictionaries and need to iterate through them and check for the keys that exist already. 我有一个字典列表,需要遍历它们并检查已经存在的键。 I have implemented a python code to manually calculate a score as below. 我已经实现了一个python代码来手动计算得分,如下所示。 In my code, I'm manually combining keys from previous dictionaries in each iteration. 在我的代码中,我在每次迭代中手动组合先前字典中的键。 Iteration will start from dict11. 迭代将从dict11开始。

How can I change this code to automatically iterate through a dynamic number of dictionaries and in each iteration how can I combine the keys dynamically? 如何更改此代码以自动迭代动态数量的词典,并且在每次迭代中如何动态组合键?


dict10 = {'A': 1, 'C': 2}
dict11 = {'B': 3, 'C': 4}
dict12 = {'A': 5, 'E': 6, 'F': 7}
dict13 = {'G': 8, 'E': 9}

exist_score = 0

for key in dict11.keys() & dict10.keys():
    exist_score += dict11[key]

for key in dict12.keys() & set(dict11.keys()).union(set(dict10.keys())):
    exist_score += dict12[key]

for key in dict13.keys() & set(dict12.keys()).union(set(dict11.keys()).union(set(dict10.keys()))):
    exist_score += dict13[key]

print(exist_score)

First you need to turn this into something that can be put into a loop. 首先,您需要将其变成可以放入循环的内容。 The same thing has to happen with dict11 , dict12 and dict13 : dict11dict12dict13必须发生相同的事情:

# same definition for dict10, dict11, dict12, dict13

exist_score = 0
seen_keys = set(dict10.keys())

for key in dict11.keys():
  if key in seen_keys:
    exist_score += dict11[key]
seen_keys.update(dict11.keys())

for key in dict12.keys():
  if key in seen_keys:
    exist_score += dict12[key]
seen_keys.update(dict12.keys())

for key in dict13.keys():
  if key in seen_keys:
    exist_score += dict13[key]
seen_keys.update(dict13.keys())

This should do the same thing as your script. 这应该与脚本执行相同的操作。 Now you can put that into a loop … 现在,您可以将其放入循环...

# same definition for dict10, dict11, dict12, dict13

exist_score = 0
seen_keys = set(dict10.keys())
other_dicts = [dict11, dict12, dict13]

for d in other_dicts:
  for key in d.keys():
    if key in seen_keys:
      exist_score += d[key]
  seen_keys.update(d.keys())

It makes the most sense to keep dicts in a list themselves. 将字典本身保留在列表中是最有意义的。 Putting this logic into a function is also a no-brainer. 将此逻辑放入函数中也很容易。

dicts = [
    {'A': 1, 'C': 2},
    {'B': 3, 'C': 4},
    {'A': 5, 'E': 6, 'F': 7},
    {'G': 8, 'E': 9}
]

def score_dicts(dicts):
    score = 0
    all_keys = set()
    for d in dicts:
        keys = d.keys()
        for key in keys & all_keys:
            score += d[key]
        all_keys.update(keys)
    return score

exist_score = score_dicts(dicts)

If you need to update the score periodically (one dict at a time), you can maintain the state in either a class or a closure. 如果您需要定期更新分数(一次更新一个字典),则可以在类或闭包中维护状态。

Class: 类:

class DictScorer():
    def __init__(self):
        self.exist_score = 0
        self.all_keys = set()
    def score(self, d):
        keys = d.keys()
        for key in keys & self.all_keys:
            self.exist_score += d[key]
        self.all_keys.update(keys)
        return self.exist_score

dict10 = {'A': 1, 'C': 2}
dict11 = {'B': 3, 'C': 4}
dict12 = {'A': 5, 'E': 6, 'F': 7}
dict13 = {'G': 8, 'E': 9}

scorer = DictScorer()

exist_score = scorer.score(dict10)
print(exist_score)

exist_score = scorer.score(dict11)
print(exist_score)

exist_score = scorer.score(dict12)
print(exist_score)

exist_score = scorer.score(dict13)
print(exist_score)

Closure: 关闭:

# returns a scorer which can
# be used incrementally
def create_dict_scorer():
    score = 0
    all_keys = set()
    def dict_scorer(d):
        nonlocal score
        keys = d.keys()
        for key in keys & all_keys:
            score += d[key]
        all_keys.update(keys)
        return score
    return dict_scorer

dict10 = {'A': 1, 'C': 2}
dict11 = {'B': 3, 'C': 4}
dict12 = {'A': 5, 'E': 6, 'F': 7}
dict13 = {'G': 8, 'E': 9}

scorer = create_dict_scorer()

exist_score = scorer(dict10)
print(exist_score)

exist_score = scorer(dict11)
print(exist_score)

exist_score = scorer(dict12)
print(exist_score)

exist_score = scorer(dict13)
print(exist_score)

Short magic with slicing and set operations: 切片和set操作的简短魔术

dicts = [dict10, dict11, dict12, dict13]
exist_score = 0

for i, d in enumerate(dicts[:0:-1]):
    offset = -(i - 2)
    exist_score += sum(d[k] for k in d.keys() & set().union(*dicts[offset::-1]))

print(exist_score)
  • dicts[:0:-1] - slice of dictionaries in reversed order excluding the 1st one dicts[:0:-1] -字典顺序相反的片,不包括第一个
  • -(i - 2) - negative offset to get consecutive "backward" slices for further set unions -(i - 2) -负偏移量以获得连续的“向后”切片以进一步setset

The output (the same as in your initial approach): 输出(与您的初始方法相同):

18

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM