Khi cần đếm tần suất xuất hiện của các tuple tương tự (có cùng các phần tử nhưng có thể khác thứ tự), có thể dùng Counter từ collections kết hợp map(sorted, ...) để chuẩn hóa tuple trước khi đếm.
Counter là subclass của dict giúp đếm đối tượng hashable, tạo bảng băm tự động.
map() áp dụng hàm cho mỗi phần tử iterable.
sorted() sắp xếp các phần tử trong tuple để tuple (1, 2) và (2, 1) được coi là giống nhau.
Ví dụ
from collections import Counter
# List of tuples
my_list = [(11, 14), (0, 78), (33, 67), (89, 0), (14, 11), (78, 0)]
print(f"List ban đầu: {my_list}")
# Chuẩn hóa: sắp xếp từng tuple -> (11,14) và (14,11) đều thành (11,14)
normalized = map(sorted, my_list)
print(f"Sau sorted: {list(normalized)}")
# Đếm tần suất
# Cần tạo lại map vì iterator chỉ dùng 1 lần
counter = Counter(tuple(sorted(t)) for t in my_list)
print(f"\nTần suất tuple (có sắp xếp): {dict(counter)}")
# So sánh: không sắp xếp
counter_raw = Counter(my_list)
print(f"Tần suất tuple (gốc): {dict(counter_raw)}")
Kết quả
List ban đầu: [(11, 14), (0, 78), (33, 67), (89, 0), (14, 11), (78, 0)]
Sau sorted: [(11, 14), (0, 78), (33, 67), (0, 89), (11, 14), (0, 78)]
Tần suất tuple (có sắp xếp): {(11, 14): 2, (0, 78): 2, (33, 67): 1, (0, 89): 1}
Tần suất tuple (gốc): {(11, 14): 1, (0, 78): 1, (33, 67): 1, (89, 0): 1, (14, 11): 1, (78, 0): 1}
Giải thích
map(sorted, my_list)áp dụngsorted()cho mỗi tuple, trả về list đã sắp xếp.tuple(sorted(t))chuyển lại thành tuple để có thể hash (key của Counter).Counterđếm số lần xuất hiện của mỗi tuple đã chuẩn hóa.- Kết quả:
(11, 14)và(14, 11)được gom thành 1, đếm = 2.
Các trường hợp sử dụng
# 1. Tìm cặp số xuất hiện nhiều nhất (order-independent)
pairs = [(1, 2), (2, 1), (3, 4), (1, 2), (4, 3)]
counter = Counter(tuple(sorted(p)) for p in pairs)
most_common = counter.most_common(1)
print(f"Cặp phổ biến nhất: {most_common}") # [((1, 2), 3)]
# 2. Tìm tuple trùng lặp hoàn toàn (order-sensitive)
counter_exact = Counter(my_list)
duplicates = {k: v for k, v in counter_exact.items() if v > 1}
print(f"Tuple trùng lặp chính xác: {duplicates}")
# 3. Counter trên tuple phẳng
flat = (1, 2, 2, 3, 3, 3)
print(Counter(flat)) # Counter({3: 3, 2: 2, 1: 1})
Lưu ý về hiệu năng
sorted() có độ phức tạp O(k log k) với k là độ dài tuple. Nếu tuple lớn và list nhiều phần tử, cân nhắc:
# Nếu tuple chỉ 2 phần tử: dùng min/max nhanh hơn sorted
def normalize_pair(pair):
a, b = pair
return (a, b) if a <= b else (b, a)
counter = Counter(normalize_pair(p) for p in pairs)