是否可以更改Array对象的长度?

时间:2015-09-30 22:49:56

标签: arrays ruby

如何将self中的Array改为全新数组?我如何填写下面的注释部分?

class Array
  def change_self
    #make this array be `[5,5,5]`
  end
end

我理解这一点:Why can't I change the value of self?并知道我无法将self分配给新对象。当我这样做时:

arr = [1,2,3,4,5]

arr包含对Array对象的引用。我可以向Array类添加一个改变数组的方法,例如:

 self[0] = 100

但是可以更改arr引用的数组的长度吗? 这些值如何存储在Array对象中?

3 个答案:

答案 0 :(得分:5)

您在标题和文字中提出了三个截然不同的问题:

  

是否可以使用Array方法更改Array对象的长度?

是的,有20种方法可以(可能)改变Array的长度:

  • <<将长度增加1
  • []=可以任意改变长度,具体取决于参数
  • clear将长度设置为0
  • compact!可以减少长度,具体取决于内容
  • concat可以增加长度,具体取决于参数
  • delete可以减少长度,具体取决于参数和内容
  • delete_at可以减少长度,具体取决于参数
  • delete_if / reject!可以减少长度,具体取决于参数和内容
  • fill可以增加长度,具体取决于参数
  • insert增加了篇幅
  • keep_if / select!可以减少长度,具体取决于参数和内容
  • pop缩短了篇幅
  • push增加了篇幅
  • replace可以根据参数和内容任意改变长度(它只是将Array完全替换为不同的Array
  • shift缩短了篇幅
  • slice!缩短了篇幅
  • uniq!可以减少长度,具体取决于内容
  • unshift增加了篇幅
  

当猴子修补Array类时,如何将“self”改为一个全新的数组?我如何填写下面的注释部分?

class Array
 def change_self
   #make this array be [5,5,5] no matter what
 end
end
class Array
  def change_self
    replace([5, 5, 5])
  end
end
  

这些值如何实际存储在Array对象中?

我们不知道。 Ruby语言规范没有规定任何特定的存储机制或实现策略。只要他们遵守Array方法的约定,实现者就可以自由地实现Array

作为示例,这里是Rubinius中的Array实现,我发现它相当可读(至少比YARV更多):

为了进行比较,这里是Topaz的实现:

JRuby

答案 1 :(得分:4)

arr = [1,2,3,4,5]
arr.replace([5,5,5])

我不会将新方法修补到Array中;特别是因为它已经存在。 Array#replace

答案 2 :(得分:2)

由于Array是可变的,你可以改变它的内容:

class Array
  def change_self
    self.clear
    self.concat [5, 5, 5]
  end
end

修改数组使其变为空,然后添加目标数组中的所有元素。它们仍然是两个不同的对象(即,myAry.object_id[5, 5, 5].object_id不同),但现在它们是等效的数组。

此外,数组仍然是以前的 - 只是它的内容发生了变化:

myAry = [1, 2, 3]
otherRef = myAry
previousId = myAry.object_id
previousHash = myAry.hash
myAry.change_self
puts "myAry is now #{myAry}"
puts "Hash changed from #{previousHash} to #{myAry.hash}"
puts "ID #{previousId} remained as #{myAry.object_id}, as it's still the same instance"
puts "otherRef points to the same instance - it shows the changes, too: #{otherRef}"

无论如何,我真的不知道为什么要这样做 - 你是在解决正确的问题,还是只是开玩笑的语言?