【问题标题】:Ruby: How do I use symbols to represent things in an array?Ruby:如何使用符号来表示数组中的事物?
【发布时间】:2009-04-30 17:16:51
【问题描述】:

我有一个数组,看起来像这样:

fruits_and_calories = [
  ["apple", 100],
  ["banana", 200],
  ["kumquat", 225],
  ["orange", 90]
]

我还想在数组的每个元素上调用一个方法:

fruits_and_calories.each do |f| eat(f[0], f[1])

我真的很想能够这样说:

fruits_and_calories.each do |f| eat(f[:name], f[:calories])

有没有一种方法可以让我不必更改数组中的每个项目(例如,通过迭代它并以某种方式添加符号)来实现这一点?或者,如果这太难了,有没有更好的选择?

【问题讨论】:

    标签: ruby arrays idioms


    【解决方案1】:

    最好的答案是根本不使用数组,而是使用哈希:

    fruits_and_calories = { :apple => 100,
                            :banana => 200,
                            :kumquat => 225,
                            :orange => 90}
    fruits_and_calories.each do |name, calories| 
      eat(name, calories)
    end
    

    【讨论】:

    • 其实关键是“|name,calories|”部分,它与他的原始数组数组相同......
    • 是的,数组可以工作,但设计要求散列。
    【解决方案2】:

    完全不改变数据结构,你可以改变块参数来达到同样的效果:

    fruits_and_calories.each  do |name, calories|  eat(name, calories);  end
    

    这是可行的,因为 Ruby 会自动将内部数组(["apple", 100] 等)扩展为块的参数列表('do |name,calories| ... end')。这是 Ruby 从 Lisp 继承的一个技巧,称为“解构参数”。

    【讨论】:

      【解决方案3】:

      Pesto 的答案(使用哈希)是一个很好的答案,但我想我更喜欢使用 Struct。

      Fruit = Struct.new(:name, :calories)
      
      fruits = [
        Fruit.new("apple", 100),
        Fruit.new("banana", 200),
        Fruit.new("kumquat", 225),
        Fruit.new("orange", 90)
      ]
      
      fruits.each {|f| eat(f.name, f.calories)}
      

      这也有助于将 eat 从同时使用名称和卡路里更改为使用水果实例:

      fruits.each {|f| eat(f)}
      

      【讨论】:

        【解决方案4】:

        它本身是否有某种原因必须是一个数组?这似乎是一个哈希,或者 Fruit 的一个类。

        【讨论】:

        • 不,没有理由它必须是一个数组。但这只是在单一方法中以一次性方式使用,没有其他地方使用,所以一堂课似乎使用核动力旋转锯,而我只想要一把锤子。
        • 如果我可以使用哈希而不需要为每个元素指定“这个是名称,这个是卡路里”,那也是一个很好的选择。能做到吗?
        • 是的,请参阅 Peslo 的回答。你当然也可以使用“apple”=> 100。
        • ("所以一个类看起来就像使用核动力旋转锯......") Kyle,你是说 Hash 是一个类而 Array 不是?在 Ruby 中,它们都是类。
        • 他的意思是“写一门新课”。您可以使用 :attr 水果、卡路里编写一个类,然后将它们组成一个数组。
        【解决方案5】:

        数组总是由数字索引,所以据我所知,使用标准数组是不可能的。

        我个人只是选择在代码上方使用注释来提示 f[0] 和 f[1] 代表什么。

        但如果你下定决心要这样做,我猜想在 Array 类上进行一些鸭式打字是可行的:

        
        class Array
          def name ; self[0] ; end
          def calories ; self[1] ; end
        end
        
        # then call it with:
        fruits_and_calories.each {|f| eat(f.name, f.calories) }
        

        【讨论】:

        • 请不要这样做!第一次向所有数组实例添加方法可能很有用,但这样疯狂......
        猜你喜欢
        • 1970-01-01
        • 2011-12-22
        • 2021-02-05
        • 2013-11-26
        • 2013-08-16
        • 1970-01-01
        • 1970-01-01
        • 2011-01-21
        • 2010-10-04
        相关资源
        最近更新 更多