为什么我的 returns 弄乱了我的结果?

why are my returns messing up my results?

这段代码的objective(它是一个更大的代码的一部分)是判断一个年份是否有重复的数字。这是我的代码:

def no_repeat?(year)
  year = year.to_s
  string = ''

  year.each_char{|i| string << year[i] unless string.include?(year[i])}
  year.length == string.length ? (return false) : (return true)
  end 

puts no_repeat?(1993)

它总是 returns 正确,我不明白为什么会这样。我已经尝试将三元组扩展为完整的 if 语句......仍然 returns 正确。我已经尝试将整个方法写成一个 while 循环(有两个索引将一个索引与另一个进行比较)

def no_repeat?(year)
  year = year.to_s

i = 0
while i < year.length 

    i2 = i + 1
    while i2 < year.length   

      if year[i] == year[i2]
        return false
      else
        return true
      end

      i2 += 1
    end
  i += 1
end

...仍然 returns 正确。我已经独立测试了每件事,它们都工作正常,直到我将 returns 放入。returns 是什么?我需要重新审视它。

您构造三元组的方式不正确。由于您的方法试图确保不重复任何内容,因此当 == 为真时,它应该 return true。三元本身旨在 return 一个值,而不是真正在其结果中执行像 (return false) 这样的表达式。 有效 ,但实际上不存在是非常规的。

三元应该看起来像

return year.length == string.length ? true : false

这当然可以简化,因为 == 表达式已经 return 是一个布尔值。

return year.length == string.length

其次,您对 year[i] 的使用不太正确。 String#each_char是将字符值赋给i,所以可以直接使用i。看起来您使用它的方式确实有效,但这不是迭代器变量 i 的使用方式。

这使您的方法变为:

def no_repeat?(year)
  year = year.to_s
  string = ''

  # i represents the character in this iteration
  # so you may just directly reference i here
  year.each_char{|i| string << i unless string.include?(i)}
  # If the lengths match, return true because there's no repeating character
  return year.length == string.length

  # You could omit the 'return' keyword too which is preferred by convention
  # since Ruby returns the last expression's value implicitly
  # year.length == string.length
end

你颠倒了真假陈述。否则代码有效。

这个有效:

def no_repeat?(year)
  year = year.to_s
  string = ''

  year.each_char{|i| string << year[i] unless string.include?(year[i])}
  year.length == string.length ? (return true) : (return false)
end

no_repeat?(1993) # => false
no_repeat?(2015) # => true

但是,您可以通过多种方式改进此代码。 return 关键字在 Ruby 中很少使用。事实上,它在你的例子中是完全多余的。这两种方法是等价的:

# with `return`
def no_repeat?(year)
  year = year.to_s
  string = ''

  year.each_char{|i| string << year[i] unless string.include?(year[i])}
  year.length == string.length ? (return true) : (return false)
end

# without `return`
def no_repeat?(year)
  year = year.to_s
  string = ''

  year.each_char{|i| string << year[i] unless string.include?(year[i])}
  year.length == string.length
end

其次,在方法名称中使用否定 ("no") 会使代码难以理解。我建议翻转逻辑并调用方法 repeat? 甚至更好 repeat_chars?.

最后,还有更简洁的方式来表达您使用内置 Ruby 方法编写的逻辑。这是另一种实现方式(我相信其他 Rubyists 可以提出更优雅的解决方案):

def repeat_chars?(year)
  year = year.to_s
  year.length != year.chars.uniq.length
end