KurinchiMalar
KurinchiMalar

Reputation: 608

Find Symmetric pairs in python

I have the below code to find and print all symmetric pairs from given input.

'''
 Given a list of number pairs.
 If pair(i,j) exist, and pair(j,i) exist report all such pairs.
'''

def find_all_symmetric_pairs(inp_dic):

    for key in inp_dic:
        val = inp_dic[key]

        if inp_dic[val] == key:
            return key,val
    return -1,-1


inp_dic = {'1':'3','2':'6','3':'5','7':'4','5':'3','8':'7'}

print type(inp_dic)
key,value = find_all_symmetric_pairs(inp_dic)

print "key:"+str(key)
print "value:"+str(value)

Output:

 key:3
 value:5

But if I change the input to

inp_dic = {(1,3),(2,6),(3,5),(7,4),(5,3),(8,7)}

or

inp_dic = {{1,3},{2,6},{3,5},{7,4},{5,3},{8,7}}

I have difficulty iterating. How do I achieve the same?

Upvotes: 1

Views: 2134

Answers (5)

gtlambert
gtlambert

Reputation: 11971

This seems like a useful solution:

d = {'1':'3','2':'6','3':'5','7':'4','5':'3','8':'7'}
pairs = [(key, value) for key, value in d.items()]
answer = [(x, y) for (x, y) in pairs if (y, x) in pairs]
print(answer)

Output

[('3', '5'), ('5', '3')]

It may also be faster if we make pairs a set instead of a list:

d = {'1':'3','2':'6','3':'5','7':'4','5':'3','8':'7'}
pairs = {(key, value) for key, value in d.items()}
answer = [(x, y) for (x, y) in pairs if (y, x) in pairs]
print(answer)

Output

[('3', '5'), ('5', '3')]

Upvotes: 4

KurinchiMalar
KurinchiMalar

Reputation: 608

I fixed the issue the following way. Hence answering my own question.

def find_all_symmetric_pairs(inp_dic):

    for key in inp_dic.iterkeys():
        val = inp_dic.get(key)

        if inp_dic.get(val) == key:
            yield key,val
    return 


inp_dic = [(1,3),(2,6),(3,5),(7,4),(5,3),(8,7)]

inp_dic = dict(inp_dic)

for key, val in find_all_symmetric_pairs(inp_dic):
print "key: " + str(key)
print "value: " + str(val)

Upvotes: 1

Mad Physicist
Mad Physicist

Reputation: 114548

Your function find_all_symmetric_pairs actually only finds one symmetric pair. You can either make it into a generator function that will really iterate over all the keys:

def find_all_symmetric_pairs(inp_dic):

    for key in inp_dic:
        val = inp_dic[key]

        if inp_dic[val] == key:
            yield key,val
    return -1,-1

for key, val in find_all_symmetric_pairs(inp_dic):
    print "key: " + str(key)
    print "value: " + str(val)

or you can do the generation manually by appending to a list:

def find_all_symmetric_pairs(inp_dic):
    keys = []
    vals = []
    for key in inp_dic:
        val = inp_dic[key]

        if inp_dic[val] == key:
            keys.append(key)
            vals.append(val)
    return keys, vals

for key, val in zip(*find_all_symmetric_pairs(inp_dic)):
    print "key: " + str(key)
    print "value: " + str(val)

Keep in mind that inp_dic = {(1,3),(2,6),(3,5),(7,4),(5,3),(8,7)} creates a set of tuples, while inp_dic = {{1,3},{2,6},{3,5},{7,4},{5,3},{8,7}} attempts to create a set of sets, which is illegal because sets are mutable and therefore unhashable. The first case will require more complex iteration than just using a dictionary because you will have to search all of the tuples for a matching key or value. To get around this, you can easily convert to a dictionary using a dictionary comprehension:

inp_dic = {(1,3),(2,6),(3,5),(7,4),(5,3),(8,7)}
inp_dic = {x[0]: x[1] for x in inp_dic}

Upvotes: 1

rbp
rbp

Reputation: 1898

with a generator https://wiki.python.org/moin/Generators

def find_all_symmetric_pairs(inp_dic):

    for key in inp_dic:
        val = inp_dic[key]

        if inp_dic[val] == key:
            yield key,val

Upvotes: 2

Wayne Werner
Wayne Werner

Reputation: 51907

Well, for one you're changing the type of inp_dic to a set of tuples or a set of sets - which apparently shouldn't even work, since sets are unhashable:

>>> input_set = {{1,3}, {3,3}}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'set'

But you can iterate over the set of tuples like this:

input_set = {(1,3), (42,23)}
for a, b in input_set:
    print(a, b)

Upvotes: 1

Related Questions