Ruby方法条件

时间:2015-09-28 17:52:17

标签: ruby methods

我的程序的指令是创建一个方法,该方法接受一个字符串并返回任何奇数周围的破折号,但最终结果可能不会以破折号"-"开始或结束。例如,如果我输入"95601137",则应返回

"9 - 5 - 6 0 - 1 - 1 - 3 - 7"

以下是代码:

def dashes(number)
  string = number.to_s
  i=0
  final = []
  while i<string.length
    digit = string[i].to_i
    if ((digit)%2 != 0) && (i==0) && (string.length == 1) && ((string.length - 1) == 0)
      final.push(string[i])
    elsif ((digit)%2 != 0) && (i==0) && (string.length != 1) && ((string.length - 1) > 0)
      final.push(string[i] + "-")
    elsif ((digit)%2 != 0) && (i>0) && (i!=(string.length - 1)) && ((string.length != 1))
      final.push("-" + string[i] + "-")
    elsif ((digit)%2 != 0) && (i!=0) && (i==(string.length - 1))
      final.push("-" + string[i])
    else final.push(string[i])
    end
    i+=1
  end
  return final
end

puts("Give me any number.")
answer = gets
puts dashes(answer)

我的计划有两个问题:

  1. 当我输入9时,它会返回"9-"。怎么样?
  2. 当我输入一个以奇数结尾的字符串时,它会在结尾处添加一个短划线,这是不期望的。我以为我也严格遵守if条件。

5 个答案:

答案 0 :(得分:2)

我想提出另一个解决方案:

def dashes(num)
  str = num.to_s
  dashed_arr = str.chars.map.with_index do |digit, index|
    next digit if digit.to_i.even?
    if index.zero? # is it first digit?
      "#{digit} -"
    elsif index == str.length - 1 # is it last digit?
      "- #{digit}"
    else 
      "- #{digit} -"
    end
  end

  dashed_arr.join(' ').gsub('- -', '-')
end

puts dashes(95601137)
puts dashes(909)
# => "9 - 5 - 6 0 - 1 - 1 - 3 - 7"
# => "9 - 0 - 9"

让我们一步一步地审核:

  1. str = num.to_s - 将我们的号码转换为字符串表示形式,即"95601137"
  2. str.chars - 用字符拆分我们的字符串。我们得到一组字符,如:["9", "5", "6", "0", "1", "1", "3", "7"],因为我们想逐个迭代它们。
  3. map接受一个数组并通过do ... end中提供的代码将其转换为另一个数组。
  4. 例如,让我们来看看这段代码:

    [1, 2, 3].map do |num| 
      num * 2 
    end
    # => [2, 4, 6]
    

    如果您还需要元素的索引,您可以类似地使用.map.with_index(索引从零开始):

    [1, 2, 3].map.with_index do |num, index| 
      num * index # index takes values 0, 1, 2
    end 
    # => [0, 2, 6]
    

    因此,在上面的代码块中,我们将数字中的每个数字设为digit,将其基于0的位置设为index

    1. next digit if digit.to_i.even?。我们不需要偶数,所以我们可以跳过它们。将.to_i转换为整数需要digit,因此我们可以查询它是偶数还是奇数。 next digit只返回当前数字并将执行移至下一位。

    2. 现在我们只留下奇数位,所以我们只需要正确地填写短划线,具体取决于数字位置:如果它是第一个数字,请附加短划线,如果它是&#39 ;最后一位数字然后将短划线放在数字前面,否则只用破折号包围数字:

      if index.zero? # first digit, index is zero-based
        "#{digit} -"
      elsif index == str.length - 1 # last digit
        "- #{digit}"
      else 
        "- #{digit} -"
      end
      
    3. 我们将中间结果保存在dashed_arr变量中以使代码可读。现在它包含以下内容:["9 -", "- 5 -", "6", "0", "- 1 -", "- 1 -", "- 3 -", "- 7"]。如您所见,我们差不多完成了,我们只需要将数组的所有元素连接回字符串。

    4. dashed_arr.join(' ')。将数组元素连接到一个字符串中,并将单个空格作为分隔符。我们得到这个字符串:9 - - 5 - 6 0 - 1 - - 1 - - 3 - - 7。嗯,似乎我们需要删除一些连续的破折号。

    5. 让我们使用gsubdashed_arr.join(' ').gsub('- -', '-')gsub只搜索所有第一个字符串,并用第二个字符串替换它们,这正是我们所需要的:9 - 5 - 6 0 - 1 - 1 - 3 - 7

    6. 我们已经完成了!我希望你和我一样有趣。

答案 1 :(得分:2)

另一项实施,受Cary Swoveland's first implementation的启发:

str = '95601137'

separators = str.each_char.map(&:to_i).each_cons(2).map do |pair| 
  pair.any?(&:odd?) ? ' - ' : ' '
end

str.chars.zip(separators).join
# => "9 - 5 - 6 0 - 1 - 1 - 3 - 7"

答案 2 :(得分:1)

替换:

answer = gets

使用:

answer = gets.strip

然后,您将获得输入的正确输出:9

因为,当您提供9作为输入并点击enter时,您的输入实际上是:"9\n",其长度为2.这就是打印{{1}的原因}}。 使用:9-gets.strip只需strip

要移除上一个\n(如果有),您可以使用chomp

-

并且,要删除第一个final_result = final.join('').chomp('-') (如果有),您可以使用以下逻辑:

-

以下是代码的完整工作版本(保留代码):

   if final_result[0] == '-'
    final_result[1..-1]
   else
    final_result
   end

答案 3 :(得分:1)

以下是两种方式:

str = "95601137"

使用枚举器

使用此方法,您可以使用String#each_char创建一个枚举器,您可以向其发送方法Enumerator#nextEnumerator#peek

enum = str.each_char

s = ''
loop do
  c = enum.next
  s << c
  n = enum.peek
  s << ((c.to_i.odd? || n.to_i.odd?) ? ' - ' : ' ')
end
s #=> "9 - 5 - 6 0 - 1 - 1 - 3 - 7"

这里的关键是,当枚举数位于最后一个元素('7')时,peek会引发StopIteration异常。 Kernel#loop通过突破循环来处理异常。

使用String#gsub

我们可以使用gsub三次,每次都使用正则表达式:

  • 将破折号放在正确的位置
  • 破折号周围的空间
  • 偶数位之间的空格

r = /       
    (\A\d) # match beginning of string followed by a digit, save in group 1
    |      # or
    (\d\z) # match a digit followed by end of string, save in group 2
    |      # or
    (\d)   # match a digit, save in capture group 3
    /x     # extended mode

str = "95601137"

str.gsub(r) do |s|
  if $1
    $1.to_i.odd? ? "#{$1}-"  : $1
  elsif $2
    $2.to_i.odd? ? "-#{$2}"  : $2 
  elsif $3
    $3.to_i.odd? ? "-#{$3}-" : $3
  else
    raise ArgumentError, "'#{s}' is not a digit" 
  end
end.gsub(/-+/, ' - ').gsub(/(\d)(\d)/,'\1 \2')
  #=> "9 - 5 - 6 0 - 1 - 1 - 3 - 7"

答案 4 :(得分:0)

一个天真的实现,可能有一些更聪明的方法来实现它:

def dashes(number)
  number                              # => 95601137
    .to_s                             # => "95601137"
    .chars                            # => ["9", "5", "6", "0", "1", "1", "3", "7"]
    .map(&:to_i)                      # => [9, 5, 6, 0, 1, 1, 3, 7]
    .map {|i| i.odd? ? "-#{i}-" : i } # => ["-9-", "-5-", 6, 0, "-1-", "-1-", "-3-", "-7-"]
    .join                             # => "-9--5-60-1--1--3--7-"
    .gsub(/^-|-$/, '')                # => "9--5-60-1--1--3--7"
    .gsub('--', '-')                  # => "9-5-60-1-1-3-7"
end