我的程序的指令是创建一个方法,该方法接受一个字符串并返回任何奇数周围的破折号,但最终结果可能不会以破折号"-"
开始或结束。例如,如果我输入"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)
我的计划有两个问题:
9
时,它会返回"9-"
。怎么样?if
条件。答案 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"
让我们一步一步地审核:
str = num.to_s
- 将我们的号码转换为字符串表示形式,即"95601137"
str.chars
- 用字符拆分我们的字符串。我们得到一组字符,如:["9", "5", "6", "0", "1", "1", "3", "7"]
,因为我们想逐个迭代它们。map
接受一个数组并通过do ... end
中提供的代码将其转换为另一个数组。 例如,让我们来看看这段代码:
[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
。
next digit if digit.to_i.even?
。我们不需要偶数,所以我们可以跳过它们。将.to_i
转换为整数需要digit
,因此我们可以查询它是偶数还是奇数。 next digit
只返回当前数字并将执行移至下一位。
现在我们只留下奇数位,所以我们只需要正确地填写短划线,具体取决于数字位置:如果它是第一个数字,请附加短划线,如果它是&#39 ;最后一位数字然后将短划线放在数字前面,否则只用破折号包围数字:
if index.zero? # first digit, index is zero-based
"#{digit} -"
elsif index == str.length - 1 # last digit
"- #{digit}"
else
"- #{digit} -"
end
我们将中间结果保存在dashed_arr
变量中以使代码可读。现在它包含以下内容:["9 -", "- 5 -", "6", "0", "- 1 -", "- 1 -", "- 3 -", "- 7"]
。如您所见,我们差不多完成了,我们只需要将数组的所有元素连接回字符串。
dashed_arr.join(' ')
。将数组元素连接到一个字符串中,并将单个空格作为分隔符。我们得到这个字符串:9 - - 5 - 6 0 - 1 - - 1 - - 3 - - 7
。嗯,似乎我们需要删除一些连续的破折号。
让我们使用gsub
:dashed_arr.join(' ').gsub('- -', '-')
。 gsub
只搜索所有第一个字符串,并用第二个字符串替换它们,这正是我们所需要的:9 - 5 - 6 0 - 1 - 1 - 3 - 7
。
我们已经完成了!我希望你和我一样有趣。
答案 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#next和Enumerator#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通过突破循环来处理异常。
我们可以使用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