[英]Ruby - Create a hash, where Keys are newly initialized Array objects
Please bear with me...I need basic concepts...I am not aware of advanced prog concepts yet. 请忍受...我需要基本概念...我还不知道高级编概念。
I have a class called Circle which initializes and calculates area
我有一个叫做Circle的类,它可以初始化和计算
area
class Circle
def initialize (radius)
@radius = radius
end
def area
3.14*@radius*@radius
end
end
I want to take user input and create however many instances of Circle
objects and its sides. 我想接受用户输入并创建
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
The $s[]
now holds array of objects I created. $s[]
现在保存我创建的对象数组。
Now, I want to do something like, 现在,我想做类似的事情,
area_array[] = 0
area_array[Circle1] = Circle1.area
area_array[Circle1] = Circle2.area
and so on...where Circle1 and Circle2 are the objects I created earlier in my while loop.... 依此类推...其中Circle1和Circle2是我在while循环中先前创建的对象。
Can someone tell me how can I put each of the created object in another array and assign an area value to it? 有人可以告诉我如何将每个创建的对象放在另一个数组中并为其分配区域值吗?
Do you need another array because you will modify or destroy the properties of the Circles in the first array? 您是否需要另一个数组,因为您将在第一个数组中修改或破坏Circles的属性? If so, and you can rely on the Cirlces' order in the array remaining the same, then just use the index value to correlate the values:
如果是这样,您可以依靠数组中Cirlces的顺序保持不变,则只需使用索引值将这些值关联起来即可:
circle_area_hash = $s.reduce{|a, c| a[c.object_id] = c.area }
Also, consider that for your analyses, you may care more about the values, than the objects, per se . 另外,考虑到进行分析时,您可能更关心值而不是对象本身 。 So then you could create
这样就可以创建
circle_area_hash = $s.reduce do |a, c|
a[c.area] = (a[c.area].nil?) ? [c] : a[c.area] << c
end
This make the hash-keys bey the area value as, and the hash-values are each an array of the objects that have that area. 这使哈希键成为区域值,哈希值分别是具有该区域的对象的数组。
Then to get the key (largest area) you can: 然后,要获取密钥 (最大区域),您可以:
circle_area_hash.max_by{|k,v| v.count}
Also, as a thought: 另外,作为一个想法:
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
To create a new array of areas: 要创建新的区域数组:
area_array = $s.map{ |circle| circle.area }
area_array = $s.map( &:area ) # Same thing, but shorter
To create one big hash: 要创建一个大哈希:
areas = Hash[ $s.map{ |circle| [ circle, circle.area ] } ]
This creates an array of arrays like: 这将创建一个数组数组,例如:
[
[ <Circle @radius=3>, 28.27 ],
[ <Circle @radius=4>, 50.27 ],
…
]
…and then uses the Hash.[]
method to convert that into a Hash. …然后使用
Hash.[]
方法将其转换为Hash。
Another technique is: 另一种技术是:
areas = $s.inject({}){ |hash,circle| hash.merge(circle=>circle.area) }
For more details, read up on Array#map
and Enumerable#inject
. 有关更多详细信息,请阅读
Array#map
和Enumerable#inject
。
However, why would you want to create this hash? 但是,为什么要创建此哈希? It seems like you're perhaps wanting to only calculate the area once each.
似乎您可能只想每个计算一次面积。 Although it's not needed for this simple calculation, you can memoize a method's return value with a pattern like this:
尽管此简单计算不需要它,但您可以使用以下模式来记忆方法的返回值:
class Circle
def initialize(radius)
@radius = radius
end
def area
@area ||= Math::PI*@radius*@radius
end
end
This will calculate the area the first time it's needed, and store it in an instance variable; 这将在第一次需要时计算面积,并将其存储在实例变量中; thereafter it will just use the value of that variable as the return value of the method, without needing to recalculate it.
之后,它将仅使用该变量的值作为方法的返回值,而无需重新计算它。
This is very straightforward. 这很简单。 You should just iterate over
$s
, using each element as a hash key and the result of its area
as the corresponding value. 您应该仅在
$s
进行迭代,将每个元素用作哈希键,并将其area
的结果用作相应的值。
Another few points that should be useful to you: 还有几点对您有用:
You can use Math::PI
instead of 3.14
您可以使用
Math::PI
而不是3.14
You should only use p
for debugging. 您只应使用
p
进行调试。 It prints the result of the inspect
method of its parameter, which is rarely what you want for tidy output. 它打印其参数的
inspect
方法的结果,这很少是您想要整洁输出的结果。 Use print
if you want to make your newlines explicit in the string, or puts
to append a newline if there isn't one already 使用
print
,如果你想使你的换行符明确字符串中,或puts
追加一个换行符如果没有一个已
It is rarely appropriate to use while
in Ruby. 这是很少适合使用
while
在Ruby中。 In this instance you just want i.times do { ... }
在这种情况下,您只想
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
However it seems more appropriate to memoize the area
method here, writing it as 但是,似乎更适合在此处记住
area
方法,将其写为
def area
@area = Math::PI * @radius * @radius unless @area
@area
end
Then you can use the method repeatedly and the calculation will be done only once. 然后,您可以重复使用该方法,并且计算将仅执行一次。
After reading your comment on NewAlexandria's answer, perhaps something like this would work for you: 在阅读了您对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
where s
is a pre-defined hash that may contain keys for instances of other circles, rectangles, etc. 其中
s
是预定义的哈希,其中可能包含其他圆形,矩形等的实例的键。
This only makes sense, however, if you plan to add additional constants or methods to your shape classes that you will want to reference with the keys of s
. 但是,仅当您计划向形状类添加其他常量或方法时,才需要使用
s
的键进行引用,这才有意义。
You should edit your question to incorporate your comment above. 您应该编辑问题以纳入上面的评论。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.