簡體   English   中英

Ruby-創建一個哈希,其中的鍵是新初始化的Array對象

[英]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#mapEnumerable#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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM