-2

I'm trying to get symmetric pairs with no duplicates, for example, from

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

, I want to get like[(2,6), (3,5), (3,4)], finding symmetric pairs.

this is my full code,

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

def find_symmetric_pairs(L):
    temp = {}
    temp_list = []
    for i in L:
        key, value = i
        for j in L:
            key_j, value_j = j
            if key == value_j and value == key_j:
                temp_list.append(tuple((key,value)))
    return temp_list

and also, I'm trying to implement this function by using python hashtable, how can I use hashtable? The output looks like this

[(2, 6), (3, 5), (5, 3), (6, 2), (3, 4), (4, 3)] but I want to show the output like above what I first told you... [(2,6), (3,5), (3,4)]

JYP
  • 57
  • 3

3 Answers3

2

You just need to add a check to see if the symmetric pair is already added to your result or not,

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

res = set()

#Convert the list to a set
L = set(L)
# Iterate through the set
for t in L:
    # If the a tuple is present , and the reversed tuple is not in the result set already
    if (t[1], t[0]) in L and (t[1], t[0]) not in res:
        # Add it to result set
        res.add(t)

print(res)

The output will be

{(2, 6), (4, 3), (3, 5)}

Another approach is to reorder tuples so that first element is bigger then second, and count tuples via collections.Counter. The elements with count 2 will be the symmetric pairs

from collections import Counter

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

#reorder tuple so that first element is bigger then second
L = [(t[1], t[0]) if t[0] < t[1] else t for t in L]

#Make a counter 
c = Counter(L)

#Count elements with count 2
res = [key for key, value in c.items() if value == 2]
print(res)

The output will be

[(6, 2), (5, 3), (4, 3)]
Aran-Fey
  • 39,665
  • 11
  • 104
  • 149
Devesh Kumar Singh
  • 20,259
  • 5
  • 21
  • 40
2

There are no hash tables as such in Python, but you can use sets. The following combines the original set of tuples set(L) with a set of reversed tuples {(y, x) for x, y in L}. It later keeps only the pairs with the smaller first element:

pairs = set(L) & {(y, x) for x, y in L}
{(x,y) for x,y in pairs if x < y}
#{(2, 6), (3, 4), (3, 5)}
DYZ
  • 55,249
  • 10
  • 64
  • 93
  • @Aran-Fey The answer wasn't even correct, in the first place. – DYZ Jun 02 '19 at 08:13
  • Wasn't it? I'm pretty sure it was. (I *did* think "this isn't correct, is it?!" at least 3 times in those 5 minutes though, before I finally understood what's going on) – Aran-Fey Jun 02 '19 at 08:15
  • @Aran-Fey It was correct by chance, just for this example. – DYZ Jun 02 '19 at 08:19
  • 1
    "There are no hash tables as such in Python" I am decently sure ``dict`` is a hash table. – MisterMiyagi Jun 02 '19 at 08:19
  • 1
    Actually this does have a minor bug (probably): If there are any symmetric tuples like `(1, 1)` in the input, they'll be included in the output even if they only occur once. Debatable if that's really a bug, but it's worth noting anyhow. – Aran-Fey Jun 02 '19 at 08:22
  • @MisterMiyagi Dictionaries are implemented as hash tables but they are not called hash tables. – DYZ Jun 02 '19 at 08:22
  • @Aran-Fey No, symmetric tuples will not be included (because of the condition `x – DYZ Jun 02 '19 at 08:24
  • 1
    What hash tables are called does not change the fact that they do exist in Python. It seems like a very misleading statement. – MisterMiyagi Jun 02 '19 at 08:29
  • @MisterMiyagi That's why I said "_as such_". Also, see [this](https://stackoverflow.com/a/2061406/4492932). – DYZ Jun 02 '19 at 08:30
  • 1
    Python's ``dict`` specifically uses ``hash`` for its keys. As such, a *dictionary* might be any kind of mapping, but ``dict`` is a hashtable or at the very least functionally indistinguishable from one (in case someone wants to drag PyPy's JIT or strategies into this). – MisterMiyagi Jun 02 '19 at 10:26
1

You could use a set if you want to disregard order. Specifically a frozenset will allow you to hash and therefore use Counter:

from collections import Counter
L_set_counter = Counter(map(frozenset, set(L)))

Now L_set_counter contains:

Counter({frozenset({2, 6}): 2, frozenset({3, 5}): 2, frozenset({3, 4}): 2, frozenset({1, 3}): 1, frozenset({4, 7}): 1})

And do find duplicates (v==2 to make it more specific, this is more generic):

dups = {k for k, v in L_set_counter.items() if v > 1}

And now dups contains:

{frozenset({3, 4}), frozenset({3, 5}), frozenset({2, 6})}
Reut Sharabani
  • 30,449
  • 6
  • 70
  • 88