[英]Ruby - Create a hash, where Keys are newly initialized Array objects
請忍受...我需要基本概念...我還不知道高級編概念。
我有一個叫做Circle的類,它可以初始化和計算area
class Circle
def initialize (radius)
@radius = radius
end
def area
3.14*@radius*@radius
end
end
我想接受用戶輸入並創建Circle
對象及其側面的許多實例。
p "How many Circles"
i = gets.to_i
j = 1
while j != i+1
p "Enter radius of Circle #{j}"
$s << Circle.new(gets.to_i)
j = j +1
end
$s[]
現在保存我創建的對象數組。
現在,我想做類似的事情,
area_array[] = 0
area_array[Circle1] = Circle1.area
area_array[Circle1] = Circle2.area
依此類推...其中Circle1和Circle2是我在while循環中先前創建的對象。
有人可以告訴我如何將每個創建的對象放在另一個數組中並為其分配區域值嗎?
您是否需要另一個數組,因為您將在第一個數組中修改或破壞Circles的屬性? 如果是這樣,您可以依靠數組中Cirlces的順序保持不變,則只需使用索引值將這些值關聯起來即可:
circle_area_hash = $s.reduce{|a, c| a[c.object_id] = c.area }
另外,考慮到進行分析時,您可能更關心值而不是對象本身 。 這樣就可以創建
circle_area_hash = $s.reduce do |a, c|
a[c.area] = (a[c.area].nil?) ? [c] : a[c.area] << c
end
這使哈希鍵成為區域值,哈希值分別是具有該區域的對象的數組。
然后,要獲取密鑰 (最大區域),您可以:
circle_area_hash.max_by{|k,v| v.count}
另外,作為一個想法:
puts "How many Circles"
$s = (1...gets.to_i).each |j|
puts "Enter radius of Circle #{j}"
$s << Circle.new(gets.to_i)
end
$s[3].area
要創建新的區域數組:
area_array = $s.map{ |circle| circle.area }
area_array = $s.map( &:area ) # Same thing, but shorter
要創建一個大哈希:
areas = Hash[ $s.map{ |circle| [ circle, circle.area ] } ]
這將創建一個數組數組,例如:
[
[ <Circle @radius=3>, 28.27 ],
[ <Circle @radius=4>, 50.27 ],
…
]
…然后使用Hash.[]
方法將其轉換為Hash。
另一種技術是:
areas = $s.inject({}){ |hash,circle| hash.merge(circle=>circle.area) }
有關更多詳細信息,請閱讀Array#map
和Enumerable#inject
。
但是,為什么要創建此哈希? 似乎您可能只想每個計算一次面積。 盡管此簡單計算不需要它,但您可以使用以下模式來記憶方法的返回值:
class Circle
def initialize(radius)
@radius = radius
end
def area
@area ||= Math::PI*@radius*@radius
end
end
這將在第一次需要時計算面積,並將其存儲在實例變量中; 之后,它將僅使用該變量的值作為方法的返回值,而無需重新計算它。
這很簡單。 您應該僅在$s
進行迭代,將每個元素用作哈希鍵,並將其area
的結果用作相應的值。
還有幾點對您有用:
您可以使用Math::PI
而不是3.14
您只應使用p
進行調試。 它打印其參數的inspect
方法的結果,這很少是您想要整潔輸出的結果。 使用print
,如果你想使你的換行符明確字符串中,或puts
追加一個換行符如果沒有一個已
這是很少適合使用while
在Ruby中。 在這種情況下,您只想i.times do { ... }
class Circle
def initialize (radius)
@radius = radius
end
def area
Math::PI * @radius * @radius
end
end
print 'How many Circles: '
i = gets.to_i
shapes = []
i.times do |n|
print "Enter radius of Circle #{n+1}? "
shapes << Circle.new(gets.to_i)
end
area_hash = {}
shapes.each do |shape|
area_hash[shape] = shape.area
end
但是,似乎更適合在此處記住area
方法,將其寫為
def area
@area = Math::PI * @radius * @radius unless @area
@area
end
然后,您可以重復使用該方法,並且計算將僅執行一次。
在閱讀了您對NewAlexandria答案的評論后,也許這樣的事情對您有用:
p "How many Circles"
(1..gets.to_i) do |j|
c = Circle.new
p "Enter radius of Circle #{j}"
s[c] = c.area(gets.to_i)}
end
其中s
是預定義的哈希,其中可能包含其他圓形,矩形等的實例的鍵。
但是,僅當您計划向形狀類添加其他常量或方法時,才需要使用s
的鍵進行引用,這才有意義。
您應該編輯問題以納入上面的評論。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.