如果我做对了,以下是一个好的开始:
def letter_remove(from_str, target_str):
"""
For each letter of from_str - remove it and check if it matches target_str
"""
for i in range(len(from_str)):
new_word = from_str[:i] + from_str[i+1:]
if new_word == target_str:
print(target_str,"--- ",from_str)
def difference(s):
list=s.split(" ")
for word1 in list:
for word2 in list:
if word1==word2:
continue
letter_remove(word2, word1)
letter_remove(word1, word2)
s="car ucar nor or caar"
difference(s)
这会给你:
$ python2 ~/tmp/test.py
('car', '--- ', 'ucar')
('car', '--- ', 'caar')
('car', '--- ', 'caar')
('car', '--- ', 'ucar')
('or', '--- ', 'nor')
('or', '--- ', 'nor')
('car', '--- ', 'caar')
('car', '--- ', 'caar')
观察:
- 我们需要将 word1 与 word2 进行比较,反之亦然,因为从 word1 中删除一个字母可能会导致 word2
- 结果需要去重
更好的(也许)版本
- 我们可以使用集合来保证集合中的元素是唯一的
- 我们将集合中的每个组合添加为元组,而不是打印
- 我们退回所有套装并在最后打印出来
def letter_remove(from_str, target_str):
"""
For each letter of from_str - remove it and check if it matches target_str
Returns:
A set of unique combinations found
"""
results = set()
for i in range(len(from_str)):
new_word = from_str[:i] + from_str[i+1:]
if new_word == target_str:
# Sort words
a, b = target_str, from_str
results.add((target_str, from_str))
return results
def difference_set(s):
list=s.split(" ")
all_results = set()
for word1 in list:
for word2 in list:
if word1==word2:
continue
all_results.update(letter_remove(word2, word1))
all_results.update(letter_remove(word1, word2))
return all_results
# This returns a set (unique elements) of the found differences
s="car ucar nor or caar"
sets = difference_set(s)
for s in sets:
print(s)
上面的输出是
$ python2 ~/tmp/test.py
('or', 'nor')
('car', 'caar')
('car', 'ucar')
观察:
- 上述算法效率非常低,因为它会为所有可能的字母删除创建太多字符串,我不建议将它用于很长的输入。更智能的算法可以比较单词中的每个字母并允许跳过一个不匹配的索引
绝对更好的方法
内嵌评论
def letter_remove2(from_str, target_str):
"""
For each letter of from_str - remove it and check if it matches target_str
Returns:
True: if the two strings can be matched by removing a character from one
"""
skipped_a_letter = False
i = 0
j = 0
# if they differ by more than a letter, then we do not accept them
if abs(len(from_str) - len(target_str)) > 1:
return False
# Loop target's letters
while i < len(target_str):
if target_str[i] == from_str[j]:
j += 1
i += 1
continue
# If we have not already skipped a letter from from_str, skip this one
# by increasing j but not i!
if not skipped_a_letter:
j += 1
# Ensure we have not exceeded the length of from_str
if len(from_str) <= j:
return False
skipped_a_letter = True
continue
# If we reach here, it means that character do not match and we have
# already attempted to skip a letter - no match after all
return False
# If we successfully loop, it means that we can match by removing a letter
return True
def difference_set(s):
list=s.split(" ")
all_results = set()
for word1 in list:
for word2 in list:
if word1==word2:
continue
if letter_remove2(word2, word1):
# Keep the target word first in the set since it will always
# be the shorter one
all_results.add((word1, word2))
if letter_remove2(word1, word2):
all_results.add((word2, word1))
return all_results
输出:
('or', 'nor')
('car', 'caar')
('car', 'ucar')