【问题标题】:Why can't I modify values of an array in a method?为什么我不能在方法中修改数组的值?
【发布时间】:2011-08-23 10:20:48
【问题描述】:

在下面的代码片段中,数组deck 应该等于[6,9,5,6,5,1,2],因为Ruby 通过引用传递数组。方法调用后,deck 的值不会改变。这是为什么呢?

def count_cut!(deck)
  s1, s2 = deck[0, deck.last], deck[deck.last..-2]
  deck = s2 + s1 + [deck.last]
end

deck = [5, 1, 6, 9, 5, 6, 2]
count_cut!(deck)
p deck

我正在使用 Ruby 1.9.2-p180。

【问题讨论】:

    标签: ruby arrays


    【解决方案1】:

    分配给deck 不会改变传入的数组。它在函数定义范围内被视为局部变量。如果你真的想改变它,你可以打电话给deck.replace

    【讨论】:

    • 如果deck是方法范围内的局部变量,为什么deck.replace会改变deck?还是赋值只是一个特例?
    • 当您调用deck = s2 + s1 + [deck.last] 时,您会创建一个新对象。如果您在方法中分配之后puts deck.object_idcount_cut!(deck) 之后,您可以测试它
    • 赋值是一种特殊情况,如果你想这样想的话。在 Ruby 中,所有值都是通过引用传递的,因此任何修改实例的方法都会为每个人修改它。但是赋值会将该变量更改为指向一个新实例。
    • 我相信 Ruby 按值传递引用
    【解决方案2】:

    按照 Ruby 的方式进行操作:不要修改原始数组,而是返回修改后的数组:

    def count_cut(deck)
      s1, s2 = deck[0, deck.last], deck[deck.last..-2]
      s2 + s1 + [deck.last]
    end
    

    然后调用者将返回值赋给deck

    deck = [5, 1, 6, 9, 5, 6, 2]
    deck = count_cut(deck)
    p deck
    

    但请考虑将其全部封装在一个 Deck 类中,尤其是当一个 Deck 有其他行为时:

    class Deck
    
      def initialize(cards)
        @cards = cards
      end
    
      def count_cut!
        s1, s2 = @cards[0, @cards.last], @cards[@cards.last..-2]
        @cards = s2 + s1 + [@cards.last]
      end
    
    end
    
    deck = Deck.new [5, 1, 6, 9, 5, 6, 2]
    deck.count_cut!
    p deck
    

    【讨论】:

      【解决方案3】:

      Array 的 .+ 方法为您提供一个 Array。使用 .unshift 修改原始对象。

      deck = [1,2,3,4,5]
      p deck.object_id #some_number
      deck = [6] + deck
      p deck.object_id #another_number
      deck.unshift([7])
      p deck.object_id #unchanged 
      

      【讨论】:

        【解决方案4】:

        您没有修改 deck 变量引用的数组,您只是将一个新数组分配给局部变量 deck

        deck = s2 + s1 + [deck.last]
        

        上面创建了一个新数组,其内容为s2 + s1 + [deck.last],然后将这个新数组分配给局部变量deckdeck 最初引用的数组保持不变。如果你想改变数组,那么你需要这样的东西:

        deck_last = deck.last
        deck.clear
        deck.push(*s2)
        deck.push(*s1)
        deck.push(deck_last)
        

        否则您将失去局部变量 deck 与其引用的非局部数组之间的连接。

        【讨论】:

          猜你喜欢
          • 2022-01-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-03-28
          • 1970-01-01
          • 1970-01-01
          • 2020-10-24
          • 1970-01-01
          相关资源
          最近更新 更多