Robin Andrews
Robin Andrews

Reputation: 3804

Combinations of 4 and 3 elements from dictionary

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.

Upvotes: 2

Views: 53

Answers (2)

martineau
martineau

Reputation: 123531

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}

Upvotes: 1

Sayandip Dutta
Sayandip Dutta

Reputation: 15872

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

Upvotes: 1

Related Questions