foo bar 没有打印正确的输出

foo bar not printing the correct output

目前我的代码将显示 1 到 100,但当它被 3 或 5 或两者整除时实际上不会打印出 case 语句....我在这里做错了什么?

def display(item_count)
  n = 1  
  while n <= item_count
    case n
    when n % 3 == 0 
      puts "foo"
    when n % 5 == 0
      puts "bar"
    when (n % 3 ==0 && n % 5 == 0) 
      puts "foobar"
    else
      puts "#{n}"
    end #--  case end stmt
    n = n + 1
  end #while end statement
end #end satement for metod

puts " How many items do you want to see"
item_count = gets.chomp.to_i
puts "#{display(item_count)}"
print "Enter amount of times> "
(1..gets.to_i).each do |i|
  puts(
    "".tap do |res|
      res << "foo" if (i % 3).zero?
      res << "bar" if (i % 5).zero?
      res << i.to_s if res.empty?
    end)
end

展示东西是一回事;将函数的结果存储在内存中以供进一步使用(例如通过网络连接或存储进行传输)是另一回事。在 ruby 中,一切都是对象,因此您应该对对象进行操作。这就是 ruby 的目的。

编辑以解决多次循环和可读性问题。

我的原作被批评为不可读,然后有人想出了一个使用 lambda 文字和猴子修补的单子解决方案。即使是经验丰富的程序员也会面临遵循其逻辑的挑战,并且解释器中涉及的堆栈操作无论如何都会将可伸缩性抛出 window。单个循环中的程序块可以解决所有这些问题,而不是迂腐。 "Readable" 也意味着 "understandable."

在 ruby >= 2.4 中不需要冻结字符串文字;它们应该被自动冻结,但由于单循环解决方案是为了解决可伸缩性问题(想象一下调用它一百万次),因此不应忽视这一优化。此外,我已将其缩减为块内的单个条件语句,这意味着更大的可扩展性。

print 'How many items do you want to see: '.freeze

list = (1..gets.to_i).collect do |i|
  div_by_3 = (i % 3).zero?
  div_by_5 = (i % 5).zero?
  case 
    when div_by_3 && div_by_5
      :foobar
    when div_by_3
      :foo
    when div_by_5
      :bar
    else
     i
  end
end

puts list.to_s

输出:

How many items do you want to see: 50
[1, 2, :foo, 4, :bar, :foo, 7, 8, :foo, :bar, 11, :foo, 13, 14, :foobar, 16, 17, :foo, 19, :bar, :foo, 22, 23, :foo, :bar, 26, :foo, 28, 29, :foobar, 31, 32, :foo, 34, :bar, :foo, 37, 38, :foo, :bar, 41, :foo, 43, 44, :foobar, 46, 47, :foo, 49, :bar]

case expression 使用 === 将您给它的参数与每个 when 表达式进行比较(在大多数情况下与 == 相同)。所以你的代码大致相当于

if (n % 3 == 0) === n
  puts "foo"
elsif (n % 5 == 0) === n
  puts "bar"
elsif (n % 3 == 0 && n % 5 == 0) === n
  puts "foobar"
else
  puts "#{n}"
end

所有 when 表达式 return truefalse,所以每个案例都失败了,你最终进入了 else。只需使用此 if 格式而不是 case,您就可以做您想做的事(尽管您需要重新安排条件以获得正确的输出)。

您可以在 ruby 中使用不带参数的 case 语句。 when 子句仍必须 return true 或 false。

case
when true
  puts 'this happens'
when false
  puts 'this does not happen'
end

因此,如果您简单地更改

,原始 post 中的代码将起作用(至少,case 语句)
case n

进入

case

并将 'foobar' 测试移至 "when" 列表的顶部。我的另一个答案也使用了这个结构,但消除了堆栈操作并产生了一个 storable/transmittable 对象,而不仅仅是显示结果。

注意:调用零?对象上的方法比将它与文字 0 进行比较要快。(x.zero? 比 x == 0 快)。