所以我需要为Array创建一个实例方法,它接受两个参数,一个数组的大小和一个将附加到数组的可选对象。
如果size参数小于或等于Array.length或size参数等于0,则只返回数组。如果可选参数留空,则输入nil。
示例输出:
array = [1,2,3]
array.class_meth(0) => [1,2,3]
array.class_meth(2) => [1,2,3]
array.class_meth(5) => [1,2,3,nil,nil]
array.class_meth(5, "string") => [1,2,3,"string","string"]
以下是我一直在处理的代码:
class Array
def class_meth(a ,b=nil)
self_copy = self
diff = a - self_copy.length
if diff <= 0
self_copy
elsif diff > 0
a.times {self_copy.push b}
end
self_copy
end
def class_meth!(a ,b=nil)
# self_copy = self
diff = a - self.length
if diff <= 0
self
elsif diff > 0
a.times {self.push b}
end
self
end
end
我已经能够创建破坏性方法class_meth!,但似乎无法找到使其具有非破坏性的方法。
答案 0 :(得分:1)
这里(恕我直言)是一个更清洁的解决方案:
class Array
def class_meth(a, b = nil)
clone.fill(b, size, a - size)
end
def class_meth!(a, b = nil)
fill(b, size, a - size)
end
end
我认为它应该满足您的所有需求。为了避免代码重复,你可以让任何一种方法调用另一种方法(当然,不能同时调用两种方法):
def class_meth(a, b = nil)
clone.class_meth!(a, b)
end
或:
def class_meth!(a, b = nil)
replace(class_meth(a, b))
end
答案 1 :(得分:0)
self_copy = self
不制作新对象 - assignment in Ruby never "copies" or creates a new object implicitly。
因此,非破坏性案例适用于相同的对象(调用该方法的实例),就像在破坏性案例中一样,不同的变量绑定到同一个对象 - 即{{ 3}}是真的。
最简单的解决方案是仅使用self.equal? self_copy
:
def class_meth(a ,b=nil)
self_copy = self.clone # NOW we have a new object ..
# .. so we can modify the duplicate object (self_copy)
# down here without affecting the original (self) object.
end
如果#clone
无法使用,则其他解决方案涉及#clone
, keeping in mind it is a shallow clone operation或获取数组create a new array(返回新数组)或甚至追加(返回新数组)#slice ;但是,与#clone
不同,它们通常会锁定返回一个数组而不是任何可能派生的子类型。
在进行上述更改后,还应该明白它可以这样写:
def class_meth(a ,b=nil)
clone.class_meth!(a, b) # create a NEW object; modify it; return it
# (assumes class_meth! returns the object)
end
使用其中一种形式来避免修改当前实例的#class_meth!
或#class_meth
的更合适的实现仍然是一个练习。
FWIW:那些是实例方法,这是合适的,而不是&#34; class meth [ods]&#34 ;;不要被错误的命名所迷惑。
答案 2 :(得分:0)
当你的问题被诊断出来时,我会就你如何做到这一点提出一个建议。我假设你想要传递两个,可选择三个,而不是一个,也可以选择两个参数。
<强>代码强>
class Array
def self.class_meth(n, arr, str=nil)
arr + (str ? ([str] : [nil]) * [n-arr.size,0].max)
end
end
<强>实施例强>
Array.class_meth(0, [1,2,3])
#=> [1,2,3]
Array.class_meth(2, [1,2,3])
#=> [1,2,3]
Array.class_meth(5, [1,2,3])
#=> [1,2,3,nil,nil]
Array.class_meth(5, [1,2,3], "string")
#=> [1,2,3,"string","string"]
Array.class_meth(5, ["dog","cat","pig"])
#=> [1,2,3,"string","string"]
Array.class_meth(5, ["dog","cat","pig"], "string")
#=> [1,2,3,"string","string"]
Array.class_meth(5, ["dog","cat","pig"])
#=> ["dog", "cat", "pig", nil, nil]
Array.class_meth(5, ["dog","cat","pig"], "string")
#=> ["dog", "cat", "pig", "string", "string"]
在撤回答案之前,@ PatriceGahide建议使用Array#fill。那将是一个改进;即,用以下内容替换操作线:
arr.fill(str ? str : nil, arr.size, [n-arr.size,0].max)