Combinations of 4 and 3 elements from dictionary

Viewed 38

I need to split a dictionary of student scores into all possible combinations of groups of 4 and groups of 3.

So far I have

from itertools import combinations

student_scores = {"A": 68, "B": 77, "C": 82, "D": 85, "E": 53, "F": 64, "G": 71}
groups_of_4 = list(map(dict, combinations(student_scores.items(), 4)))

The trouble comes when I try to get the compliment of these groups of 4. It seems to involve some kind of dictionary difference operator, but my research has not yielded any clarity on how to achieve this - some answers say I need to use sets, others not.

The best I've managed is

print(groups_of_4[0], {k: v for k, v in student_scores.items() if k not in groups_of_4[0]})

giving a single combination, but I can't see how to modify this to work for all the combinations, especially as the dictionary comprehension only checks for a single item.

Any help solving this much appreciated.

2 Answers

You have to find the complement using set difference operation of dict.items objects, and convert them back to dict:

>>> from itertools import combinations

>>> groups_of_4 = list(map(dict, combinations(student_scores.items(), r=4)))

>>> groups_of_3 = [dict(student_scores.items() - other.items()) for other in groups_of_4]

>>> groups_of_3
[{'G': 71, 'E': 53, 'F': 64},
 {'G': 71, 'F': 64, 'D': 85},
 {'G': 71, 'E': 53, 'D': 85},
 {'E': 53, 'F': 64, 'D': 85},
 {'G': 71, 'F': 64, 'C': 82},
 ...
 {'G': 71, 'B': 77, 'A': 68},
 {'F': 64, 'B': 77, 'A': 68},
 {'E': 53, 'B': 77, 'A': 68},
 {'D': 85, 'B': 77, 'A': 68},
 {'B': 77, 'C': 82, 'A': 68}]

You can find more about how set properties are implemented in dictionary view objects in PEP 3106

I'm not exactly sure what you're after, but the following (for groups of 4) looks promising:

from itertools import combinations

def complement(group, scores):
    diff = scores.keys() - group.keys()
    return {k: scores[k] for k in diff}


student_scores = {"A": 68, "B": 77, "C": 82, "D": 85, "E": 53, "F": 64, "G": 71}
groups_of_4 = list(map(dict, combinations(student_scores.items(), 4)))

for group in groups_of_4:
    print(group, 'complement', complement(group, student_scores))

Output:

{'A': 68, 'B': 77, 'C': 82, 'D': 85} complement {'E': 53, 'F': 64, 'G': 71}
{'A': 68, 'B': 77, 'C': 82, 'E': 53} complement {'F': 64, 'G': 71, 'D': 85}
{'A': 68, 'B': 77, 'C': 82, 'F': 64} complement {'E': 53, 'G': 71, 'D': 85}
{'A': 68, 'B': 77, 'C': 82, 'G': 71} complement {'E': 53, 'F': 64, 'D': 85}
{'A': 68, 'B': 77, 'D': 85, 'E': 53} complement {'C': 82, 'F': 64, 'G': 71}
{'A': 68, 'B': 77, 'D': 85, 'F': 64} complement {'C': 82, 'E': 53, 'G': 71}
{'A': 68, 'B': 77, 'D': 85, 'G': 71} complement {'C': 82, 'E': 53, 'F': 64}
{'A': 68, 'B': 77, 'E': 53, 'F': 64} complement {'C': 82, 'G': 71, 'D': 85}
{'A': 68, 'B': 77, 'E': 53, 'G': 71} complement {'C': 82, 'F': 64, 'D': 85}
{'A': 68, 'B': 77, 'F': 64, 'G': 71} complement {'C': 82, 'E': 53, 'D': 85}
{'A': 68, 'C': 82, 'D': 85, 'E': 53} complement {'B': 77, 'F': 64, 'G': 71}
{'A': 68, 'C': 82, 'D': 85, 'F': 64} complement {'E': 53, 'B': 77, 'G': 71}
{'A': 68, 'C': 82, 'D': 85, 'G': 71} complement {'E': 53, 'B': 77, 'F': 64}
{'A': 68, 'C': 82, 'E': 53, 'F': 64} complement {'B': 77, 'G': 71, 'D': 85}
{'A': 68, 'C': 82, 'E': 53, 'G': 71} complement {'B': 77, 'F': 64, 'D': 85}
{'A': 68, 'C': 82, 'F': 64, 'G': 71} complement {'E': 53, 'B': 77, 'D': 85}
{'A': 68, 'D': 85, 'E': 53, 'F': 64} complement {'C': 82, 'B': 77, 'G': 71}
{'A': 68, 'D': 85, 'E': 53, 'G': 71} complement {'C': 82, 'B': 77, 'F': 64}
{'A': 68, 'D': 85, 'F': 64, 'G': 71} complement {'C': 82, 'E': 53, 'B': 77}
{'A': 68, 'E': 53, 'F': 64, 'G': 71} complement {'C': 82, 'B': 77, 'D': 85}
{'B': 77, 'C': 82, 'D': 85, 'E': 53} complement {'F': 64, 'G': 71, 'A': 68}
{'B': 77, 'C': 82, 'D': 85, 'F': 64} complement {'E': 53, 'G': 71, 'A': 68}
{'B': 77, 'C': 82, 'D': 85, 'G': 71} complement {'E': 53, 'F': 64, 'A': 68}
{'B': 77, 'C': 82, 'E': 53, 'F': 64} complement {'G': 71, 'D': 85, 'A': 68}
{'B': 77, 'C': 82, 'E': 53, 'G': 71} complement {'F': 64, 'D': 85, 'A': 68}
{'B': 77, 'C': 82, 'F': 64, 'G': 71} complement {'E': 53, 'D': 85, 'A': 68}
{'B': 77, 'D': 85, 'E': 53, 'F': 64} complement {'C': 82, 'G': 71, 'A': 68}
{'B': 77, 'D': 85, 'E': 53, 'G': 71} complement {'C': 82, 'F': 64, 'A': 68}
{'B': 77, 'D': 85, 'F': 64, 'G': 71} complement {'C': 82, 'E': 53, 'A': 68}
{'B': 77, 'E': 53, 'F': 64, 'G': 71} complement {'C': 82, 'D': 85, 'A': 68}
{'C': 82, 'D': 85, 'E': 53, 'F': 64} complement {'B': 77, 'G': 71, 'A': 68}
{'C': 82, 'D': 85, 'E': 53, 'G': 71} complement {'B': 77, 'F': 64, 'A': 68}
{'C': 82, 'D': 85, 'F': 64, 'G': 71} complement {'E': 53, 'B': 77, 'A': 68}
{'C': 82, 'E': 53, 'F': 64, 'G': 71} complement {'B': 77, 'D': 85, 'A': 68}
{'D': 85, 'E': 53, 'F': 64, 'G': 71} complement {'C': 82, 'B': 77, 'A': 68}
Related