很抱歉出现noob问题,但是这个星号在范围开始时是什么意思?
class Matrix
def initialize(matrix_string)
@matrix = matrix_string.split("\n").map do |row|
row.split.map(&:to_i)
end
@rows = rows.length
@cols = columns.length
end
def rows
@matrix
end
def columns
@matrix.transpose
end
# --->>***
def saddle_points
[*0...@rows].product([*0...@cols]).select do |coords|
saddle_point?(*coords)
end
# ***<----
end
private
def saddle_point?(row, col)
(@matrix[row][col] == rows[row].max) &&
(@matrix[row][col] == columns[col].min)
end
end
答案 0 :(得分:2)
您可以使用
Array
(或splat)运算符将*
转换为参数列表:arguments = [1, 2, 3] my_method(*arguments)
对Range
可以这样做:
arguments = 1..3
my_method(*arguments) # essentially the same as my_method(1, 2, 3)
在数组声明内的范围之前也允许使用splat运算符将Range
隐式转换为Array
:
[*1..3]
#⇒ [1, 2, 3]
答案 1 :(得分:1)
*
通过“拆分”其内容并将其转换为数组来解压缩数组。
答案 2 :(得分:1)
如其他答案所述,*
运算符用于将数组转换为参数列表。
但是,如果您的对象不是数组,该怎么办?然后,Ruby将在对象上调用#to_a
(如果已定义),并改用返回的数组。否则,将使用对象本身。
在这种情况下,对象既不是数组也不定义#to_a
:
x = *4 # => [4]
如果对象定义了#to_a
,则将像Range
那样调用和使用该对象:
x = *0..1 # => [0, 1]
为了证明这一点,我们可以在模块之前添加一个跟踪到#to_a
的调用:
module Trace
def to_a
puts "#to_a called"
super
end
end
Range.prepend(Trace)
x = *0..1
# prints "#to_a called"
# => [0, 1]
请注意,如果您的对象已经是#to_a
类型,那么Ruby将不会调用Array
。
我们也可以在自定义类型上使用它:
class Foo
def to_a
[1, 2, 3]
end
end
x = *Foo.new # => [1, 2, 3]
顺便说一句,Ruby的nil
也实现了#to_a
。这使我们可以像传递任何内容一样传递nil
作为参数,因为nil.to_a
返回[]
:
def count(*args)
args.count
end
count # => 0
count(*0..1) # => 2
count(*nil) # => 0
当您将一个可能为nil
的变量传递给具有默认值的方法时,这很有用:
def say_hi(name = "Jane")
puts "Hi, #{name}"
end
name = nil
say_hi(*name) # prints "Hi, Jane"
但是,如果我们删除NilClass#to_a
:
NilClass.undef_method(:to_a)
say_hi(*name) # prints "Hi, "