0

请耐心等待...我需要基本概念...我还不知道高级 prog 概念。

我有一个名为 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 循环中创建的对象...。

有人能告诉我如何将每个创建的对象放在另一个数组中并为其分配一个区域值吗?

4

4 回答 4

2

您是否需要另一个数组,因为您将修改或破坏第一个数组中 Circles 的属性?如果是这样,并且您可以依靠 Circles 在数组中的顺序保持不变,那么只需使用索引值来关联这些值:

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
于 2013-09-20T20:34:49.120 回答
2

要创建一个新的区域数组:

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.[]方法将其转换为哈希。

另一种技术是:

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

这将在第一次需要时计算面积,并将其存储在实例变量中;此后它将只使用该变量的值作为方法的返回值,而无需重新计算它。

于 2013-09-20T20:52:17.983 回答
1

这非常简单。您应该只迭代$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

然后您可以重复使用该方法,并且只进行一次计算。

于 2013-09-20T20:58:01.963 回答
0

在阅读了您对 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

wheres是一个预定义的散列,它可能包含其他圆形、矩形等实例的键。

但是,这仅在您计划向形状类添加额外的常量或方法时才有意义,您希望使用s.

您应该编辑您的问题以合并您的上述评论。

于 2013-09-20T21:10:04.360 回答