如何删除3个或更多相同的字符

时间:2018-11-18 13:14:32

标签: ruby

在学习Ruby的过程中,我遇到了这个练习。我正在尝试连续删除3个或更多相同的字符。测试用例输入:abbbaaccada输出:ccada输入:bbccdddcb输出:(空字符串)

到目前为止,我有不返回预期结果的解决方案:

def playground("abbbaaccada")
  count = string.length
  string.chars.each_with_index.map { |v, i| (v * (count - i)).capitalize }.join('')
end

output gives me
==> AaaaaaaaaaaBbbbbbbbbbBbbbbbbbbBbbbbbbbAaaaaaaAaaaaaCccccCcccAaaDdA
instead of
==> ccada

能请你指教吗?

编辑: 忘记添加不允许使用正则表达式

4 个答案:

答案 0 :(得分:1)

这里有两个挑战:

  • 匹配并删除一行中的所有字符或更多字符
  • 如果上一步创建了新的三分,请递归再次测试

这里是一种方法:

THREE_OR_MORE = /(.)\1{2,}/
def three_is_too_many(str)
  if str.match? THREE_OR_MORE
    str = three_is_too_many(str.gsub(THREE_OR_MORE, ''))
  end
  str
end

正则表达式查找任何字符('。'),然后查找其自身字符('\ 1'),两次或更多次('{2,}')。

然后例程要么a)删除三个或更多并再次测试,要么b)返回字符串。

答案 1 :(得分:1)

这是一个潜在的解决方案。以下方法搜索具有重复的数组的任何子序列,如果存在三个或更多个,则返回重复值的范围。

def find_3_or_more(ary)
  ary.each_index do |i|
    j = i + 1
    while j < ary.length && ary[i] == ary[j]
      j += 1
    end
    return (i...j) if j - i > 2
  end
  nil
end

此部分将目标字符串分成一个char数组,并反复将在标识为重复的范围内的字符切成薄片,直到没有重复为止,如nil范围所示。

def delete_3_or_more(str)
  ary = str.chars
  while r = find_3_or_more(ary)
    ary.slice!(r)
  end
  return ary.join
end

似乎可以完成您的测试用例。

答案 2 :(得分:0)

def recursively_remove_runs_of_3_or_more(str)
  arr = str.chars
  loop do
    a = arr.slice_when { |a,b| a.downcase != b.downcase }.to_a
    b = a.reject! { |e| e.size > 2 }
    arr = a.flatten
    break arr.join if b.nil?
  end
end

recursively_remove_runs_of_3_or_more "abbbaaccada"
  #=> "ccada"

这使用Enumerable#slice_when(MRI v2.2中的新功能)。请注意,Array#reject!在未进行任何更改时将返回nil

您也可以使用Enumerable#chunk_while(MRI v2.3中的新增功能)。只需替换:

    a = arr.slice_when { |a,b| a.downcase != b.downcase }.to_a

具有:

    a = arr.chunk_while { |a,b| a.downcase == b.downcase }.to_a

chunk_whileslice_when是阴和阳。

如果可以使用正则表达式并且在没有问题的情况下,您可以编写:

str = "abbbaaccada"
s = str.dup
loop { break(s) if s.gsub!(/(.)\1{2,}/, '').nil? }
  #=> "ccada"

答案 3 :(得分:0)

(我想发表评论,但这还不允许我这样做。) 假设您正在尝试学习,我选择只给您一些提示,同时避免解决方案。

使用正则表达式或/和某些String方法可能会有更短的方法。但是,您说不能使用正则表达式。

我的建议是,仅尝试使用到目前为止介绍的部分来解决该问题。它可能不一定是最优雅的解决方案,但是您可以随着进度进行修改。正如其他人所建议的,递归可能是一个不错的选择。但是,如果您对此还不熟悉,则可以尝试对字符串进行切片并合并所需的部分。可以将其与无限循环结合使用,以检查新字符串是否满足您的条件:但是请考虑何时需要退出循环

此外,在您的代码中:

  

v * (count - i)

String#*实际上为您提供了count - i的{​​{1}}的副本,它们是串联在一起的。