我遇到了这个代码问题 - 我需要遍历一系列布尔值100次。说明:
戴着帽子的猫
你有100只猫。你的规则很简单:每当你访问一只猫时,你都会切换它的帽子状态(如果它已经有一顶帽子,你将其删除......如果它没有帽子,你可以将它打开)。所有的猫都开始无帽了。你循环100轮拜访猫。在第一轮,你会看到每只猫。在第二轮,你访问每一只猫。在第n轮,您将访问每一只猫......直到第100轮,您只能访问第100只猫。在100轮结束时哪只猫有帽子?
来自JS的Ruby新手,并坚持如何实现这一点。我认为我的逻辑是正确的,我无法让它改变数组中布尔值的值。
任何建议都非常感谢!
由于
def cats_in_hats
cats = []
i = 0
while i< 100
cats << false
i = i + 1
end
puts cats
round = 1;
while round < 10
#
cats = cats.each_with_index do |cat, idx|
if idx % round == 0
puts "toggle index #{idx} divisible by round #{round}"
cat = !cat
puts cat
end
end
round = round + 1
end
puts cats
end
puts "------Cats in Hats------"
puts cats_in_hats == [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
答案 0 :(得分:3)
欢迎来到红宝石。有人很好地解释了代码的问题。我想我会尽快给你一个红宝石物体的力量。
让我们从Cat
开始吧。它能做什么?良好:
好的,让我们为此做一个Object
:
class Cat
def initialize
@hat = false # start out without a hat
end
def toggle_hat
!@hat # in case you just want to tip your hat in salutation to JörgWMittag
end
def toggle_hat!
@hat = toggle_hat # @hat equals not(@hat) e.g. @hat = not(true) to take off the hat
end
def has_hat?
@hat # does it have a hat true or false
end
end
完美有Cat
。现在让我们看一下这个问题。
我们需要遍历100 cats
。好
cats = Array.new(100) { Cat.new }
现在我们有100只猫。让我们开始循环
#loop from 1 up to 100 providing the loop number (n)
1.upto(100).each do |n|
# for each n we skip over the preceding n and step by n
(n..100).step(n) do |idx|
# pick the appropriate cat (ruby indexes start at 0)
# toggle his hat
cats[idx - 1].toggle_hat!
end
end
很棒我们所有的Cat
已经通过并切换现在让我们计算带帽子的人
# will count each cat where has_hat? is true
cats.count {|cat| cat.has_hat? }
#=> 10
这通常会更加惯用地表达为cats.count(&:has_hat?)
。这使用了ruby的Symbol#to_proc
糖,意味着在每个元素上调用方法has_hat?
,如上面更明确地显示的那样。
我们也可以收集它们
cats.map.with_index {|cat,idx| idx + 1 if cat.has_hat? }.compact
#=> [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
Tada Object
是令人惊叹的,并且可以用于非常简单的简单代码。 Full Example
答案 1 :(得分:1)
cats = cats.each_with_index do |cat, idx|
# ...
cat = !cat
end
这就是问题所在。 Ruby中的所有对象都通过指针在内存中表示,并且这些指针被复制以将对象传递给方法/块/等。因此,当您执行each_with_index
时,Ruby会将每个元素的指针一次复制到块本地变量cat
中。
现在当你说cat = !cat
时,这就是Ruby所做的事情
!
指向的对象的cat
方法并调用它。这将返回指向对象true
或对象false
cat
醇>
这个新指针决不会在你的cats
数组中结束!
我可以想到这个问题的两个主要解决方案:
cats
中存储可变对象。然后你可以在每个cat
上调用一个方法来告诉它改变它的状态(这就是@ engineermnky的代码所做的)cat
,而是告诉Ruby将新指针直接复制到数组中:cats[idx] = !cat
答案 2 :(得分:0)
def cats_in_hats
cats = []
i = 0
while i < 100
cats << false
i = i + 1
end
p cats
round = 1;
while round < 100
cats = cats.collect!.with_index do |cat, idx|
idx % round == 0 ? !cat : cat
end
round = round + 1
end
p cats
end
puts "------Cats in Hats------"
puts cats_in_hats
您的初始代码的问题在于您从未做过&#34;做&#34; each_with_index
块中的任何内容。当您使用cat = !cat
时,您只是在循环范围内更改该项,而从不创建新数组。使用.collect!.with_index
map/collect!.with_index(to get the index),您可以对数组中的每个项执行操作,并在每次迭代时返回一个新数组。这与JavaScript map
函数的工作方式类似。如果您需要进一步解释,请告诉我。