在编写比较2个单词的方法时,如何检查单词是否只有1个字母不同?我假设单词长度相同,字母顺序无关紧要(参见“眼镜蛇”,“bravo”)。
def one_letter_apart?(word1, word2)
我期待以下结果:
one_letter_apart?("abra","abro") == true
one_letter_apart?("cobra","bravo") == true
one_letter_apart?("bravo","tabby") == false
one_letter_apart?("abc","cab") == false
我尝试了一些操作它们的方法(拆分,排序,然后设置相等并添加到新数组,然后计数),但到目前为止都没有。非常感谢任何想法。
答案 0 :(得分:5)
这个使用了String#sub
仅替换它找到的第一件事的事实。
def one_different_char?(str, other)
other_str = other.dup
str.chars{|char| other_str.sub!(char, '')} #sub! just replaces just one occurence of char
other_str.size == 1
end
test_set = [["abra","abro"],["cobra","bravo"],["bravo","tabby"],["abc","cab"]]
test_set.each{|first, second| puts one_different_char?(first, second) }
#true
#true
#false
#false
答案 1 :(得分:4)
你想要Levenstein distance。例如,使用text gem:
require 'text'
def one_letter_apart? string1, string2
Text::Levenshtein.distance(string1, string2).eql? 1
end
one_letter_apart? "abra", "abro"
# => true
one_letter_apart? "cobra", "bravo"
# => false
答案 2 :(得分:1)
def one_letter_apart?(s1, s2)
return false if s1.length != s2.length
a2 = s2.chars.to_a
s1.chars.each do |c|
if i = a2.index(c)
a2.delete_at(i)
end
end
a2.length == 1
end
one_letter_apart?("abra","abro") == true
# => true
one_letter_apart?("cobra","bravo") == true
# => true
one_letter_apart?("bravo","tabby") == false
# => true
one_letter_apart?("abc","cab") == false
# => true
更新:回答你的工作原理问题:这是与steenslag完全相同的通用算法,但我没有考虑使用String#sub!
进行删除,所以我转换为数组并使用index
和delete_at
的组合来删除给定字符的第一个匹配项。天真的方法是a2.delete_at(a2.index(c))
,但如果c
中不存在字符a2
,则index
会返回nil
,这是{的无效输入{1}}。解决方法是仅在delete_at
返回非delete_at
的内容时才调用index
,这就是我所做的。声明nil
并将其设置为i
,并且a2.index(c)
评估该作业的值。它与:
if
我更喜欢steenslag的方法,如果我想到i = a2.index(c)
if i
# ...
,我会做同样的事情。
答案 3 :(得分:-1)
如果两个字符串具有相同的长度且只有一个不同的字母,而所有其他字母位于相同的位置,则此函数返回true:
def one_letter_apart? string1, string2
return false if string1.size != string2.size
found = false
(0...string1.size).each do |i|
next if string1[i] == string1[i]
return false if found # if found is already true, and we found another difference, then result is false.
found = true # We found the first difference.
end
found # True if only one difference was found.
end
此功能处理错误位置的字母(如“cobra”和“bravo”):
def one_letter_apart? string1, string2
letters1 = string1.chars.each_with_object(Hash.new(0)) { |c, h| h[c] += 1 }
letters2 = string2.chars.each_with_object(Hash.new(0)) { |c, h| h[c] -= 1 }
diff = letters1.merge(letters2) { |key, count1, count2| count1 + count2 }
return diff.values.select { |v| v != 0 } .sort == [-1, 1]
end