# 5 Best Ways to Count Bidirectional Tuple Pairs in Python

Rate this post

π‘ Problem Formulation: Given a list of tuples, the challenge is to count how many unique bidirectional pairs exist. A bidirectional pair is defined as two tuples where the second is a reverse of the first (i.e., (a, b) and (b, a) are considered the same pair). For example, input: [(1, 2), (2, 1), (3, 4), (4, 3)] should output: 2 unique bidirectional pairs.

## Method 1: Using a Set for Unique Pairs

This method involves iterating over the list of tuples, storing each as a frozenset in another set allowing for the storage of unique bidirectional pairs since frozensets are unordered collections.

Here’s an example:

```pairs = [(1, 2), (2, 1), (3, 4), (4, 3)]
unique_pairs = set()

for pair in pairs:

print(len(unique_pairs))```

Output: 2

In this snippet, we loop through each tuple in the list and create a `frozenset` because it is an unordered collection where (1, 2) and (2, 1) become indistinguishable. Adding these to a set ensures only unique pairs are counted, and finally, the length of the set gives the desired result.

## Method 2: Sorting Tuples Before Adding to Set

By first sorting each tuple in a standardized order before adding them to a set, we create a uniform representation of each bidirectional pair, thus enabling us to count unique pairs accurately.

Here’s an example:

```pairs = [(1, 2), (2, 1), (3, 4), (4, 3)]
unique_pairs = set()

for pair in pairs:

print(len(unique_pairs))```

Output: 2

Each tuple is sorted so that it always appears in the same order (smallest element first), and then it’s turned back into a tuple and added to the set. This ensures that all bidirectional pairs are stored in only one way, hence making it easy to count unique pairs.

## Method 3: Using a Counter with Frozensets

Utilize the `Counter` class from the `collections` module with frozensets to elegantly count and manage bidirectional tuple pairs.

Here’s an example:

```from collections import Counter

pairs = [(1, 2), (2, 1), (3, 4), (4, 3)]
counted_pairs = Counter(frozenset(pair) for pair in pairs)

print(sum(counted_pairs.values()) // 2)```

Output: 2

The code uses a generator to transform each tuple in the list into a `frozenset` and passes it to the `Counter` constructor. Since each bidirectional tuple is counted twice, we divide the total by 2 to get the count of unique bidirectional pairs.

## Method 4: Dictionary-based Method

This method involves creating a dictionary where each sorted tuple is a key, and its value is a count of occurrences. It’s effective for counting unique tuples while maintaining their original order of appearance.

Here’s an example:

```pairs = [(1, 2), (2, 1), (3, 4), (4, 3)]
counted_pairs = {}

for pair in pairs:
ordered_pair = tuple(sorted(pair))
counted_pairs[ordered_pair] = counted_pairs.get(ordered_pair, 0) + 1

print(len(counted_pairs))```

Output: 2

The `sorted` function ensures each pair is in a consistent order, which lets us use the tuple as a key in a dictionary, effectively counting unique pairs by the existence of keys in the dictionary.

## Bonus One-Liner Method 5: Using Set Comprehension

A concise and elegant Python one-liner utilizing set comprehension to achieve the same goal, it showcases Python’s ability to condense logic into a single line of code.

Here’s an example:

```pairs = [(1, 2), (2, 1), (3, 4), (4, 3)]
unique_pairs_count = len({frozenset(pair) for pair in pairs})

print(unique_pairs_count)```

Output: 2

This one-liner transforms each tuple to a `frozenset` (removing the notion of direction) and adds it to a set, automatically ensuring uniqueness. The length of the resulting set is the count of unique bidirectional pairs.

## Summary/Discussion

• Method 1: Using a Set with Frozensets. Strengths: Simple and straightforward. Weaknesses: May have slight overhead due to the creation of frozensets.
• Method 2: Sorting Tuples Before Adding to Set. Strengths: Easy to understand and follows a logical process. Weaknesses: Additional sorting step may introduce inefficiency for large lists.
• Method 3: Counter with Frozensets. Strengths: Provides additional information, like the occurrence of each pair. Weaknesses: Slightly more complex, requires understanding of the Counter class.
• Method 4: Dictionary-based Method. Strengths: Efficient in terms of maintaining the order while counting. Weaknesses: More verbose than the set-based methods.
• Method 5: Using Set Comprehension. Strengths: Very concise and Pythonic. Weaknesses: May sacrifice readability for those not familiar with comprehensions.