Khi cần tìm các ký tự xuất hiện trong CẢ HAI chuỗi, có thể dùng set và phép giao & (hoặc | cho hợp).
set chỉ chứa phần tử duy nhất. Phép & trả về phần tử chung, | trả về phần tử xuất hiện ở ít nhất một trong hai.
Ví dụ
string_1 = 'hey'
string_2 = 'jane'
print(f"Chuỗi 1: '{string_1}'")
print(f"Chuỗi 2: '{string_2}'")
# Chuyển thành set ký tự
set_1 = set(string_1)
set_2 = set(string_2)
print(f"\nSet 1: {set_1}")
print(f"Set 2: {set_2}")
# Giao (intersection) - ký tự có ở CẢ HAI
common = set_1 & set_2
print(f"\nKý tự chung (giao): {common}")
# Hợp (union) - ký tự có ở ÍT NHẤT MỘT
union = set_1 | set_2
print(f"Ký tự xuất hiện (hợp): {union}")
# Hiệu (difference) - chỉ ở chuỗi 1
diff = set_1 - set_2
print(f"Chỉ ở chuỗi 1: {diff}")
# Symmetric difference - chỉ ở MỘT trong hai
sym_diff = set_1 ^ set_2
print(f"Chỉ ở một trong hai: {sym_diff}")
Kết quả
Chuỗi 1: 'hey'
Chuỗi 2: 'jane'
Set 1: {'h', 'e', 'y'}
Set 2: {'j', 'a', 'n', 'e'}
Ký tự chung (giao): {'e'}
Ký tự xuất hiện (hợp): {'h', 'e', 'y', 'j', 'a', 'n'}
Chỉ ở chuỗi 1: {'h', 'y'}
Chỉ ở một trong hai: {'h', 'y', 'j', 'a', 'n'}
Giải thích
set('hey')->{'h', 'e', 'y'}.set('jane')->{'j', 'a', 'n', 'e'}.&(intersection):{'e'}- chỉ 'e' có trong cả hai.|(union): tất cả ký tự xuất hiện.- Kết quả là set (không giữ thứ tự).
Giữ thứ tự xuất hiện
def common_chars_ordered(s1, s2):
"""Ký tự chung, giữ thứ tự xuất hiện trong s1."""
set2 = set(s2)
seen = set()
result = []
for ch in s1:
if ch in set2 and ch not in seen:
seen.add(ch)
result.append(ch)
return result
print(common_chars_ordered('hey', 'jane')) # ['e']
print(common_chars_ordered('hello', 'world')) # ['l', 'o']
Đếm tần suất ký tự chung
from collections import Counter
s1 = 'hello world'
s2 = 'world peace'
counter1 = Counter(s1)
counter2 = Counter(s2)
# Min count cho mỗi ký tự chung
common_counts = {}
for ch in counter1.keys() & counter2.keys():
common_counts[ch] = min(counter1[ch], counter2[ch])
print(common_counts) # {'l': 1, 'o': 2, 'r': 1, 'd': 1, ' ': 1, 'e': 1}
Ứng dụng: Kiểm tra anagram
def is_anagram(s1, s2):
"""Kiểm tra 2 chuỗi có phải anagram không (bỏ qua space, case)."""
clean1 = s1.replace(' ', '').lower()
clean2 = s2.replace(' ', '').lower()
return Counter(clean1) == Counter(clean2)
print(is_anagram('listen', 'silent')) # True
print(is_anagram('hello', 'world')) # False
print(is_anagram('A gentleman', 'Elegant man')) # True
Tìm ký tự chung của NHIỀU chuỗi
strings = ['apple', 'people', 'purple', 'ample']
common = set(strings[0])
for s in strings[1:]:
common &= set(s)
print(common) # {'p', 'l', 'e'} - p, l, e có trong tất cả