Counting “unique pairs” of numbers into a python dictionary?

Counting “unique pairs” of numbers into a python dictionary?



EDIT: Edited typos; the key values of the dictionary should be dictionaries, not sets.



I will keep the typos here though, as the questions below address this question. My apologies for the confusion.



Here's the problem:



Let's say I have a list of integers whereby are never repeats:


list1 = [2, 3]



In this case, there is a unique pair 2-3 and 3-2, so the dictionary should be:


2:3: 1, 3:2: 1



That is, there is 1 pair of 2-3 and 1 pair of 3-2.



For larger lists, the pairing is the same, e.g.


list2 = [2, 3, 4]



has the dicitonary


2:3: 1, 3:2: 1, 3:4: 1, 4:3: 1, 2:4: 1, 4:2: 1



(1) Once the size of the lists become far larger, how would one algorithmically find the "unique pairs" in this format using python data structures?



(2) I mentioned that the lists cannot have repeat integers, e.g.


[2, 2, 3]



is impossible, as there are two 2s.



However, one may have a list of lists:


list3 = [[2, 3], [2, 3, 4]]



whereby the dictionary must be


2:3: 2, 3:2: 2, 3:4: 1, 4:3: 1, 2:4: 1, 4:2: 1



as there are two pairs of 2-3 and 3-2. How would one "update" the dictionary given multiple lists within a list?



This is an algorithmic problem, and I don't know of the most efficient solution. My idea would be to somehow cache values in a list and enumerate pairs...but that would be so slow. I'm guessing there's something useful from itertools.


itertools






I think you got your expected output wrong, it does not fit with what you describe.

– Olivier Melançon
Sep 6 '18 at 3:48






Agreed @OlivierMelançon; please clarify input and expected output. (your output also uses sets, which are unordered collections, whereby 3, 1, and 1, 3 are equivalent)

– Reblochon Masque
Sep 6 '18 at 3:50



3, 1


1, 3






Also, it does not make much sense... You say a number cannot be repeated, then the answer is trivially two for every possible pair.

– Olivier Melançon
Sep 6 '18 at 3:58






@OlivierMelançon I'm sorry. Please see the edit. These should be dictionary values which are dictionaries, not sets.

– ShanZhengYang
Sep 6 '18 at 14:00






@ReblochonMasque I'm sorry. Please see the edit. These should be dictionary values which are dictionaries, not sets.

– ShanZhengYang
Sep 6 '18 at 14:00




2 Answers
2



What you want is to count pairs that arise from combinations in your lists. You can find those with a Counter and combinations.


Counter


combinations


from itertools import combinations
from collections import Counter

list2 = [2, 3, 4]

count = Counter(combinations(list2, 2))

print(count)


Counter((2, 3): 1, (2, 4): 1, (3, 4): 1)



As for your list of list, we update the Counter with the result from each sublist.


Counter


from itertools import combinations
from collections import Counter

list3 = [[2, 3], [2, 3, 4]]

count = Counter()

for sublist in list3:
count.update(Counter(combinations(sublist, 2)))

print(count)


Counter((2, 3): 2, (2, 4): 1, (3, 4): 1)






Excellent use of library functions. It's almost always preferable to one-off ad-hoc code which isn't easy to debug in the editor here.

– user554538
Sep 6 '18 at 4:55



My approach iterates over the input dict (linear complexity) and pairs each key with its first available integer (this complexity depends on the exact specs of your question - e.g., can each list contain unlimited sub-lists?), inserting these into an output dict (constant complexity).


dict


import os
import sys


def update_results(result_map, tup):
# Update dict inplace
# Don't need to keep count here
try:
result_map[tup] += 1
except KeyError:
result_map[tup] = 1
return


def algo(input):
# Use dict to keep count of unique pairs while iterating
# over each (key, v[i]) pair where v[i] is an integer in
# list input[key]
result_map = dict()
for key, val in input.items():
key_pairs = list()
if isinstance(val, list):
for x in val:
if isinstance(x, list):
for y in x:
update_results(result_map, (key, y))
else:
update_results(result_map, (key, x))
else:
update_results(result_map, (key, val))
return len(result_map.keys())


>>> input = 1: [1, 2], 2: [1, 2, [2, 3]]
>>> algo(input)
>>> 5



I'm pretty sure there's a more refined way to do this (again, would depend on the exact specs of your question), but this could get your started (no imports)



Thanks for contributing an answer to Stack Overflow!



But avoid



To learn more, see our tips on writing great answers.



Required, but never shown



Required, but never shown




By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

𛂒𛀶,𛀽𛀑𛂀𛃧𛂓𛀙𛃆𛃑𛃷𛂟𛁡𛀢𛀟𛁤𛂽𛁕𛁪𛂟𛂯,𛁞𛂧𛀴𛁄𛁠𛁼𛂿𛀤 𛂘,𛁺𛂾𛃭𛃭𛃵𛀺,𛂣𛃍𛂖𛃶 𛀸𛃀𛂖𛁶𛁏𛁚 𛂢𛂞 𛁰𛂆𛀔,𛁸𛀽𛁓𛃋𛂇𛃧𛀧𛃣𛂐𛃇,𛂂𛃻𛃲𛁬𛃞𛀧𛃃𛀅 𛂭𛁠𛁡𛃇𛀷𛃓𛁥,𛁙𛁘𛁞𛃸𛁸𛃣𛁜,𛂛,𛃿,𛁯𛂘𛂌𛃛𛁱𛃌𛂈𛂇 𛁊𛃲,𛀕𛃴𛀜 𛀶𛂆𛀶𛃟𛂉𛀣,𛂐𛁞𛁾 𛁷𛂑𛁳𛂯𛀬𛃅,𛃶𛁼

Edmonton

Crossroads (UK TV series)