Khi cần thực hiện phép cộng element-wise cho nested tuple (tuple của các tuple), có thể dùng zip() lồng nhau kết hợp generator expression.
zip() gom các iterable lại theo cặp phần tử cùng vị trí.
Generator expression tạo iterator lười biếng (lazy evaluation).
Ví dụ
# Hai nested tuple cùng cấu trúc 3x2
tuple_1 = ((7, 8), (3, 4), (3, 2))
tuple_2 = ((9, 6), (8, 2), (1, 4))
print(f"Tuple 1: {tuple_1}")
print(f"Tuple 2: {tuple_2}")
# zip cấp 1: ghép hàng tương ứng -> ((7,8),(9,6)), ((3,4),(8,2)), ((3,2),(1,4))
# zip cấp 2: trong mỗi cặp hàng, ghép cột tương ứng
result = tuple(
tuple(a + b for a, b in zip(row1, row2))
for row1, row2 in zip(tuple_1, tuple_2)
)
print(f"\nKết quả cộng: {result}")
Kết quả
Tuple 1: ((7, 8), (3, 4), (3, 2)) Tuple 2: ((9, 6), (8, 2), (1, 4)) Kết quả cộng: ((16, 14), (11, 6), (4, 6))
Giải thích
zip(tuple_1, tuple_2)tạo cặp hàng:((7,8), (9,6)),((3,4), (8,2)),((3,2), (1,4)).- Generator expression ngoài:
for row1, row2 in zip(...)duyệt từng cặp hàng. zip(row1, row2)tạo cặp cột:(7,9),(8,6).- Generator expression trong:
a + b for a, b in zip(row1, row2)cộng từng cặp. tuple(...)chuyển từng hàng kết quả thành tuple.tuple(...)ngoài cùng chuyển toàn bộ thành nested tuple.
Cách khác: NumPy (khuyên dùng cho ma trận lớn)
import numpy as np arr1 = np.array(tuple_1) arr2 = np.array(tuple_2) result_np = arr1 + arr2 print(result_np) # [[16 14] # [11 6] # [ 4 6]] # Chuyển về nested tuple nếu cần result_tuple = tuple(tuple(row) for row in result_np) print(result_tuple)
Hàm chung cho nested tuple bất kỳ
def nested_tuple_op(t1, t2, op):
"""Áp dụng phép toán op cho nested tuple cùng cấu trúc."""
if isinstance(t1, tuple) and isinstance(t2, tuple):
if len(t1) != len(t2):
raise ValueError("Cấu trúc nested tuple không khớp")
return tuple(nested_tuple_op(a, b, op) for a, b in zip(t1, t2))
else:
# Phần tử lá (số) -> áp dụng op
return op(t1, t2)
import operator
print(nested_tuple_op(tuple_1, tuple_2, operator.add))
print(nested_tuple_op(tuple_1, tuple_2, operator.mul))
print(nested_tuple_op(tuple_1, tuple_2, operator.sub))
Xử lý nested tuple độ dài hàng khác nhau
from itertools import zip_longest
def nested_add_safe(t1, t2, fill=0):
"""Cộng nested tuple, điền fill cho phần tử thiếu."""
result = []
for row1, row2 in zip_longest(t1, t2, fillvalue=()):
new_row = tuple(a + b for a, b in zip_longest(row1, row2, fillvalue=fill))
result.append(new_row)
return tuple(result)
ragged_1 = ((1, 2), (3,))
ragged_2 = ((10,), (20, 30), (40, 50))
print(nested_add_safe(ragged_1, ragged_2))
# ((11, 2), (23, 30), (40, 50))