当前位置 : 主页 > 编程语言 > ruby >

数组 – 如何让我的数组只在Ruby中本地操作(在函数内)?

来源:互联网 收集:自由互联 发布时间:2021-06-23
当我运行下面的 ruby代码时,为什么我的数组被全局操作?我怎样才能在函数范围内操作数组? a = [[1,0],[1,1]]def hasRowsWithOnlyOnes(array) array.map { |row| return true if row.keep_if{|i| i != 1 } == [] } fa
当我运行下面的 ruby代码时,为什么我的数组被全局操作?我怎样才能在函数范围内操作数组?

a = [[1,0],[1,1]]

def hasRowsWithOnlyOnes(array)
  array.map { |row|
    return true if row.keep_if{|i| i != 1 } == []
  }
  false;
end

puts a.to_s
puts hasRowsWithOnlyOnes(a)
puts a.to_s

$ruby​​ test.rb输出:

[[1, 0], [1, 1]]
true
[[0], []]

我无法让它发挥作用.我甚至尝试过.select {true}并将其分配给一个新名称.范围如何在Ruby for Arrays中运行?
仅供参考,$ruby​​ -v:

ruby 2.2.1p85 (2015-02-26 revision 49769) [x86_64-linux]
这不是范围问题,而是一个传递问题的论据

> Ruby中的所有变量都是对象的引用.
>将对象传递给方法时,会生成该对象引用的副本并将其传递给该对象.

这意味着方法中的变量数组和顶级变量a引用完全相同的数组.对数组所做的任何更改也将作为a的更改显示,因为两个变量都引用同一个对象.

您的方法通过调用Array#keep_if来修改数组.hold_if方法就地修改数组.

修复

对此的最佳解决方法是使其方法不会修改传入的数组.这可以使用Enumerable#any?和Enumerable#all?方法非常巧妙地完成:

def has_a_row_with_only_ones(array)
  array.any? do |row|
    row.all? { |e| e == 1 }
  end
end

此代码表示如果对于任何行,该行中的每个元素都是1,则该方法返回true.这些方法不会修改数组.更重要的是,他们清楚地传达了方法的意图.

糟糕的解决方法

如果您希望通过数组的副本将该方法作为传递给它,以便可以修改该数组而不在该方法外部看到该修改,那么您可以对该数组进行深层复制.如this answer所示,您可以定义此方法以进行深层复制:

def deep_copy(o)
  Marshal.load(Marshal.dump(o))
end

然后,在方法的顶部,进行深层复制:

def has_a_row_with_only_ones(array)
  array = deep_copy(array)
  # code that modifies array
end

这应该避免,因为它很慢.

网友评论