1

This is a Ruby Monk exercise and I'm having trouble wrapping my head around a particular concept.

For example, "soup bowl" = "soup bowl" + 1 wouldn't be valid, so why does @dishes_needed[a] = (@dishes_needed[a] || 0) + 1 work in the code below? Is it because they are variables and not objects? If so, why doesn't code a = (a||0)+1 work when I initially set a = "Soup":

class Dish
end

class Soup < Dish
end
class IceCream < Dish
end
class ChineseGreenBeans < Dish
end

class DeliveryTray
  DISH_BOWL_MAPPING = { 
    Soup => "soup bowl",
    IceCream => "ice cream bowl",
    ChineseGreenBeans => "serving plate"
  }

  def initialize
    @dishes_needed = {}
  end

  def add(dish)
    a = DISH_BOWL_MAPPING[dish.class]
     @dishes_needed[a] = (@dishes_needed[a] || 0) + 1
  end

  def dishes_needed
      return "None." if @dishes_needed.empty?

      @dishes_needed.map { |dish, count| "#{count} #{dish}"}.join(", ")
  end
end  

d = DeliveryTray.new
d.add Soup.new; d.add Soup.new
d.add IceCream.new

puts d.dishes_needed # should be "2 soup bowl, 1 ice cream bowl"
4

3 回答 3

3

让我们简化@dishes_needed部分,以便您了解核心概念。 @dishes_needed是一个散列,并向散列@dishes_needed[a] = (@dishes_needed[a] || 0) + 1添加一个键值对。

这是查看代码的更简单的方法。这是 DISH_BOWL_MAPPING 哈希:

  DISH_BOWL_MAPPING = { 
    Soup => "soup bowl",
    IceCream => "ice cream bowl",
    ChineseGreenBeans => "serving plate"
  }

DISH_BOWL_MAPPING从哈希中获取某个元素:

>> DISH_BOWL_MAPPING[Soup]
=> "soup bowl"

@dishes_needed是一个空哈希:

>> @dishes_needed = {}
=> {}

如果a = Soup,那么下面是相关代码行的运行方式:

>> a = Soup
=> Soup
>> @dishes_needed[a] = (@dishes_needed[a] || 0) + 1
=> 1
>> @dishes_needed
=> {Soup=>1}

让我们分解方程的右手边,这是令人困惑的:

>> (@dishes_needed[a] || 0) + 1
>> (@dishes_needed[Soup] || 0) + 1
# @dishes_needed[Soup] is nil because Soup hasn't been added to the hash yet
>> (nil || 0) + 1
# nil || 0 evaluates to 0 because nil and false are falsey in Ruby
>> (0) + 1
>> 1

@dishes_needed[Soup]现在哈希已更新,随后调用以评估为 1:

>> @dishes_needed[Soup]
=> 1

这表示键 (Soup) 等于值加一(在这种情况下,值尚未建立,因此结果为 1)。

如果a = "Soup"thena = (a||0)+1计算结果为a = "Soup" + 1并且您不能在 Ruby 中添加整数和字符串。如果将 1 转换为字符串,则表达式计算正确。

a = (a||0)+1.to_s
于 2013-07-25T00:27:05.793 回答
2

我们不能在 ruby​​ 中将事物划分为变量和对象。这里的一切都是对象。

关于您的代码,唯一要了解的是 + 方法(是的,它是一种方法)不适用于字符串对象,因为您在这两种情况下都在尝试。它在这种情况下有效,因为如果对象为 NILL,您将使用 Fixnum 对象 0 对其进行初始化,并且 + 方法适用于 Fixnum。

希望我回答你。如果需要更多说明,请询问。

于 2013-07-25T04:47:13.603 回答
1

在这段代码中:

a = DISH_BOWL_MAPPING[dish.class]
@dishes_needed[a] = (@dishes_needed[a] || 0) + 1

aDISH_BOWL_MAPPING要么是哈希值之一的字符串,要么是nil键不存在。如果它是nil,那么@dishes_needed[a]也将是 nil,这使得(@dishes_needed[a] || 0)评估为0,然后您将其添加1到。这里的关键概念是如果未找到密钥则Hash#[]返回nil(除非您已将默认值设置为其他值,而您没有在这里)。显然,这里的净效果是@dishes_needed[a]如果它已经存在则增加,1如果它不存在则将其设置为。

与之对比:

a = "Soup"
a = (a||0)+1

在这里,a总是以 开头"Soup",所以(a||0)总是"Soup",您无法添加1

于 2013-07-25T00:30:05.923 回答