提问人:Seby 提问时间:7/8/2023 更新时间:7/9/2023 访问量:101
Ruby :比较两个单词并从中提取不常见的字母
ruby : compare two words and extract uncommon letters out of it
问:
我必须创建一个程序,该程序接受用户输入两个单词,并从两个单词中提取唯一的字母。
例如:两个词是“外推”和“其中”
删除常用字母表后,无论输入的单词顺序如何,结果都应为“extrpolatimg”。就像,虽然在外推中有两个“a”,但只删除了一个。
到目前为止,我编写的代码如下
puts "Enter the first_word : "
word_1 = gets.chomp.downcase.split('', 0)
puts "Enter second word name: "
word_2 = gets.chomp.downcase.split('', 0)
p word_1
p word_2
differences = word_1- word_2
p differences
#input1 = among
#input2 = extrapolation
# output => ["m","g"]
该代码忽略了第二个单词中不存在的字母。
是否有任何内置的字符串方法可以处理此问题?
提前感谢您的帮助。
答:
对于手头的任务,你可以通过稍微改变你的方法来改变它。Ruby 非常棒,它允许我们使用 chars 方法将字符串转换为字符数组。因此,您可以将 split('', 0) 替换为 chars。
这里的逻辑是首先创建第二个单词字符的副本。然后,遍历第一个单词的字符。如果在第二个单词的副本中找到字符,请将其从第一个单词和第二个单词的副本中删除。这两个词中剩下的都是独特的字符。
让我们把它变成代码:
puts "Enter the first word: "
word_1 = gets.chomp.downcase.chars
puts "Enter the second word: "
word_2 = gets.chomp.downcase.chars
copy_word_2 = word_2.dup # Create a copy of word_2 characters
word_1.each do |char|
if copy_word_2.include?(char)
word_1.delete_at(word_1.index(char))
copy_word_2.delete_at(copy_word_2.index(char))
end
end
differences = word_1 + copy_word_2 # Combine remaining unique characters from both words
puts "The unique characters are: "
p differences
在这段代码中,我们使用 delete_at 方法删除数组中特定索引处的字符,并使用 index 方法查找该字符第一次出现的索引。包括?方法检查数组是否包含某个字符。
评论
"extrplatiomg"
"extrpolatimg"
我会这样做:
puts 'Enter the first_word:'
chars1 = gets.chomp.downcase.chars
puts 'Enter second word name:'
chars2 = gets.chomp.downcase.chars
((chars1 - chars2) + (chars2 - chars1)).join
# with 'extrapolation' and 'amoug'
# => "extrpltimg"
# with 'amoug' and 'extrapolation'
# => "mgextrplti"
评论
假设我们得到两个词。
w1 = "extrapolation"
w2 = "among"
步骤 1:将每个字符串转换为字符数组
a1 = w1.chars
#=> ["e", "x", "t", "r", "a", "p", "o", "l", "a", "t", "i", "o", "n"]
a2 = w2.chars
#=> ["a", "m", "o", "n", "g"]
步骤 2:为每个数组创建一个哈希值,该哈希值给出数组中每个唯一字符的第一个实例的索引
def first_char_pos(a)
a.each_with_index.with_object({}) do |(c,i),h|
h[c] = i unless h.key?(c)
end
end
h1 = first_char_pos(a1)
#=> {"e"=>0, "x"=>1, "t"=>2, "r"=>3, "a"=>4,
# "p"=>5, "o"=>6, "l"=>7, "i"=>10, "n"=>12}
h2 = first_char_pos(a2)
#=>{"a"=>0, "m"=>1, "o"=>2, "n"=>3, "g"=>4}
第 3 步:确定要从每个单词中删除的字母
letters_to_remove = a1 & a2
#=> ["a", "o", "n"]
第 4 步:确定每个单词中要保留的字母索引
def indices_to_keep(a, h, letters_to_remove)
a.size.times.to_a - h.values_at(*letters_to_remove)
end
idx1 = indices_to_keep(a1, h1, letters_to_remove)
#=>[0, 1, 2, 3, 5, 7, 8, 9, 10, 11]
idx2 = indices_to_keep(a2, h2, letters_to_remove)
#=> [1, 4]
第 5 步:按顺序确定每个单词中要保留的字母
s1 = a1.values_at(*idx1)
#=> ["e", "x", "t", "r", "p", "l", "a", "t", "i", "o"]
s2 = a2.values_at(*idx2)
#=> ["m", "g"]
第 6 步:形成所需的字符串
s1.join + s2.join
#=> "extrplatiomg"
这与所需的字符串不同,即 。原因是我删除了要删除的每个字母的第一个实例,而通过删除每个字符串的第一个和每个字符串的最后一个来获得所需的字符串。要么是 OP 在给出所需结果时犯了错误,要么是我不明白确定要删除哪个字母实例的规则。"extrpolatimg"
"a"
"o"
我没有讨论可能出现大写字母的情况,因为我不知道适用于这种情况的规则。
评论
您可以使用 sub
替换模式的第一个匹配项:(可以是单个字符)
'extrapolation'.sub('a', '_')
#=> "extr_polation"
您还可以通过传递一个空字符串作为替换来删除第一个匹配项:
'extrapolation'.sub('a', '')
#=> "extrpolation"
这可以在循环中用于将一个字符串中的所有字符替换为另一个字符串:
input1 = 'among'
input2 = 'extrapolation'
result = input1
input2.each_char do |char|
result = result.sub(char, '')
end
result
#=> "mg"
为了避免在每次迭代时创建一个新字符串,您可以重复调用 sub!
对字符串进行修改,这会就地修改接收器。但是,由于这种修改,您必须复制
输入以避免修改:input1
result = input1.dup
input2.each_char do |char|
result.sub!(char, '')
end
result
#=> "mg"
这可以通过利用 with_object
进一步重构,这对于在方法中提供隐式返回值特别有用:
def word_diff(string1, string2)
string2.each_char.with_object(string1.dup) do |char, string|
string.sub!(char, '')
end
end
diff1 = word_diff(input2, input1)
#=> "extrplatio"
diff2 = word_diff(input1, input2)
#=> "mg"
diff1 + diff2
#=> "extrplatiomg"
从性能上讲,这种方法可能不适合(非常)大的字符串,因为它会为第二个字符串中的每个字符遍历第一个字符串一次(反之亦然)。
评论
'a'
'o'
'a'
'o'
'Extrapolation'
'Heathen'
'a'
'o'