【问题标题】:alternating cases in a string - Ruby字符串中的交替大小写 - Ruby
【发布时间】:2021-08-14 20:08:19
【问题描述】:

我想让字符串中的所有其他字符都大写。

到目前为止,我有这个代码...

    def task(s)

    n = s.length
    i = 1

    while i < n
      s[i] = s[i].upcase
      if s[i] == " "
        i = i 
      else
        i += 2
      end
    end
    s
  end

这很好用,但是我希望我的函数忽略空格。

这是我当前的输出

expected: "hElLo ThErE fRiEnD"
got: "hElLo tHeRe fRiEnD"

我该如何实现?

【问题讨论】:

  • 你试过什么?我在代码中看不到任何检查字符是否为空格的内容——也许从那里开始?
  • n的值为字符串的长度;一旦分配它就不会改变。空间比较将发生在while 循环内; n 的值无关紧要。
  • 如果您尝试过某些东西,展示它可能是个好主意。我们或许能够解释您的尝试有什么问题,但如果我们没有看到该尝试,则无法解释。
  • 如果你设置i = i(这是一个无操作)循环将永远不会继续。
  • @TomLord 感谢您的建议。我已经更改了代码以向未来的读者展示我正在尝试的内容。也许你会好心解释一下我做错了什么?

标签: ruby string


【解决方案1】:

修改您的方法,您可以改为将字符串拆分为单个字符 (.split("")),然后使用 map(一种返回通过修改数组中的每个项目创建的新数组的方法)首先检查字符是否为空格,然后如果它应该大写(up 变量),并在返回字符之前翻转up 的值。这为我们提供了一个字符数组,然后我们可以将它们与.join("") 连接在一起。

def task(s)
  up = false

  s.split("").map do |char|
    if char != " "
      if up
        char = char.upcase
      end
      up = !up
    end
    char
  end.join("")
end

puts task("hello there friend")

输出:

hElLo ThErE fRiEnD

【讨论】:

  • 这太棒了!但是,如果我想将每 3 个字符都设为大写,我该如何修改呢?示例输出为 'heLlo TheRe frieNd'
  • @TheMayerof 如果这是您的要求之一,最好在原始问题中明确说明。在努力编写解决方案之后转移目标是令人沮丧的。
  • 你说“我想让字符串中的所有其他字符都大写。”,而不是“我想让每个nth 字符大写”.
  • @TomLord 我很抱歉。我原来的问题已得到正确回答。我只是对进一步探索 kata 感到好奇。
  • 为此,请考虑其他方法来跟踪何时使用大写。这里我们有一个布尔值,可以是真/假,这意味着它将每隔一个字符交替。如果您改为使用整数和模运算符,则可以每 n 个字符交替一次。例如,如果upn 的倍数,我们将字母大写:if up % n == 0 ...
【解决方案2】:

this answer to your original question 的基础上,这是一个允许您传入upcase_frequency 参数的实现 - 因此您可以将每个第 2 个字母、每个第 3 个字母、或每个第 100 个字母或任何您想要的字母大写:

def task(s, upcase_frequency: 2)
  upcase_counter = 1

  s.split("").map do |char|
    if char != " "
      if upcase_counter % upcase_frequency == 0
        char = char.upcase
      end               
      upcase_counter += 1
    end                
    char               
  end.join("")         
end

puts task("hello there friend")
  # => hElLo ThErE fRiEnD

puts task("hello there friend", upcase_frequency: 3)
  # => heLlo TheRe fRieNd

【讨论】:

  • 还有无数其他方法可以进一步扩展它,例如:标点符号的特殊处理?还是为了数字?或者对于其他空格,比如换行符?或者对于已经是大写的字符?............
  • 一件小事:用s.each_char(它返回一个枚举器)代替s.split("")可以避免创建数组s.split("")。可以说它读起来也更好。 (汤姆知道这一点。)
【解决方案3】:
def upcase_every_so_many(str, freq)
  return str if freq.zero?
  str.gsub(/\p{L}/).with_index(1) { |c,i| (i % freq).zero? ? c.upcase : c }
end
str = "Now is the time for all good..."
puts "freq    upcase_every_so_many(freq)"
(0..17).each { |freq| puts "%03s   %020s" % [freq, upcase_every_so_many(str, freq)] }
freq    upcase_every_so_many(freq)
  0   Now is the time for all good...
  1   NOW IS THE TIME FOR ALL GOOD...
  2   NOw Is ThE tImE fOr AlL gOoD...
  3   NoW is The TimE foR alL goOd...
  4   Now Is thE timE for All gOod...
  5   Now iS the tIme foR all gOod...
  6   Now is The timE for alL good...
  7   Now is tHe time fOr all goOd...
  8   Now is thE time for All good...
  9   Now is the Time for alL good...
 10   Now is the tIme for all gOod...
 11   Now is the tiMe for all gooD...
 12   Now is the timE for all good...
 13   Now is the time For all good...
 14   Now is the time fOr all good...
 15   Now is the time foR all good...
 16   Now is the time for All good...
 17   Now is the time for aLl good... 

\p{L} 匹配每个 Unicode 字母。

请注意,我使用了String#gsub 的形式返回一个枚举器,并且我已将该枚举器链接到Enumerator#with_index


这是该方法的一种变体。

def upcase_every_so_many(str, freq)
  return str if freq.zero?
  enum = ([false]*(freq-1) + [true]).cycle
  str.gsub(/\p{L}/) { |c| enum.next ? c.upcase : c }
end
upcase_every_so_many(str, 4)
  #=> "Now Is thE timE for All gOod..."

Array#cycle

对于freq = 4

arr = [false]*(freq-1) << true
  #=> [false, false, false, true]
enum = arr.cycle
  #=> #<Enumerator: [false, false, false, true]:cycle>
enum.next
  #=> false
enum.next
  #=> false
enum.next
  #=> false
enum.next
  #=> true
enum.next
  #=> false
... ad infinitum

【讨论】:

  • 要为每个匹配的字母添加一个计数器,您还可以使用str.gsub(/\p{L}/).with_index { |c, i| ... }
  • @Stefan,感谢您的建议,这是一个很好的建议,我已将其纳入编辑中。奇怪的是,考虑到我经常使用返回枚举数的gsub 的形式,我没有想到这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-01
  • 2021-05-31
相关资源
最近更新 更多