Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Max value within array of objects

I'm new in ruby. I'm trying to do the following but haven't succeeded.

I've got an array of objects, let's call it objs. Each object has multiple properties, one of those is a variable that holds a number, let's call it val1. I wanna iterate through the array of objects and determine the max value of val1 through all the objects.

I've tried the following:

def init(objs)
  @objs = objs
  @max = 0
  cal_max
end

def cal_max

  @max = @objs.find { |obj| obj.val1 >= max }

  # also tried
  @objs.each { |obj| @max = obj.val1 if obj.val1 >= @max }

end

As I said, I'm just learning about blocks.

Any suggestion is welcome.

Thanks

like image 713
Sebastian Avatar asked Sep 17 '16 01:09

Sebastian


2 Answers

Let's say you have set up the following model:

class SomeObject
  attr_accessor :prop1, :prop2, :val1

  def initialize(prop1, prop2, val1)
    @prop1 = prop1
    @prop2 = prop2
    @val1  = val1
  end
end

#define your objects from the class above
david  = SomeObject.new('David',  'Peters', 23)
steven = SomeObject.new('Steven', 'Peters', 26)
john   = SomeObject.new('John',   'Peters', 33)

#define an array of the above objects
array = [david, steven, john]

Then use max_by by passing the condition into its block as follows to determine the object with the max val1 value. Finally call val1 to get the value of the max object.

array.max_by {|e| e.val1 }.val1 #=> 33

You may also consider using hashes (negating the need to define a new class), like so:

david  = {f_name: 'David',  s_name: 'Peters', age: 23}
steven = {f_name: 'Steven', s_name: 'Peters', age: 26}
john   = {f_name: 'John',   s_name: 'Peters', age: 33}

array = [david, steven, john]
array.max_by { |hash| hash[:age] }[:age] #=> 33
like image 50
Sagar Pandya Avatar answered Sep 28 '22 09:09

Sagar Pandya


@objs.map(&:val1).max

That will invoke the method on each object, and create a new array of the results, and then find the max value. This is shorthand for:

@objs.map{ |o| o.val1 }.max

Alternatively, you can select the object with the largest value, and then operate on it (as properly recomended by Cary Swoveland below):

@objs.max_by(&:val1).val1
like image 37
Phrogz Avatar answered Sep 28 '22 07:09

Phrogz