2

I have an array of car objects,

class Car

  def initialize(engine_size, maximum_speed, acceleration, mass)
    @engine_size = engine_size
    @maximum_speed = maximum_speed
    @acceleration = acceleration
    @mass = mass
  end

end

and I would like to list identical cars by comparing a subset of their attributes, for example: engine_size, acceleration and mass.

I have tried using group_by however this only allows me to compare the entire car object or single attributes.

6
  • 1
    Are you trying to filter an array of cars based on some common attributes, or to get a list of distinct attributes by an array of cars? Commented Jun 12, 2015 at 14:08
  • @ Francesco Pirrone - The former Commented Jun 12, 2015 at 14:20
  • Do you want to: 1) determine which cars have specified attributes (e.g., @engine_size = 1600, @mass = 2000, etc.; or 2) group cars having the same values for all for attributes? Please edit your question to clarify, as some readers may miss your answer if it's in a comment. Commented Jun 12, 2015 at 16:32
  • @Cary - I believe I have clarified my question. Commented Jun 12, 2015 at 17:53
  • It appears you want what I called option #1. Correct? Commented Jun 12, 2015 at 18:04

4 Answers 4

4
cars.group_by{|car| [car.engine_size, car.accelaration, car.mass]}
Sign up to request clarification or add additional context in comments.

1 Comment

On the basis of the OPs comments on the question, your answer appears to be the only one that is correct.
1

Let's assume you have previusly initialized an array of cars and now you want a subset of cars that have a 2000cc engine and more than 1000kg of mass:

result = cars.select{|car| car.engine==2000 and car.mass > 1000}

Also you can use select! if you need to filter in place. More about on docs.

Comments

1

This allows you to filter cars by different search attributes :

class Car

  attr_reader :engine_size, :maximum_speed, :acceleration, :mass

  def self.cars_by_attrs(cars, args = {})

    return [] if cars.empty?

    # Checking if all the arguments in args are valid
    # instance variables on all the cars.
    all_instance_vars = cars.all? do |car|
      args.all? do |key, val|
        car.instance_variables.include? "@#{key.to_s}".to_sym
      end
    end

    unless all_instance_vars
      raise ArgumentError.new('Instance variable not found.')
    end

    cars.select do |car|
      args.all? do |key, val|
        # Checking if the instance variables can be retrieved.
        unless car.respond_to?(key)
          raise ArgumentError.new('Instance variable not accessible.') 
        end
        car.send(key) == val
      end
    end
  end

  def initialize(engine_size, maximum_speed, acceleration, mass)
    @engine_size = engine_size
    @maximum_speed = maximum_speed
    @acceleration = acceleration
    @mass = mass
    @test = true
  end


end

cars = []
cars << Car.new(10, 20, 5, 6)
cars << Car.new(10, 20, 7, 8)
cars << Car.new(12, 21, 9, 10)
puts Car.cars_by_attrs(cars, engine_size: 10, maximum_speed: 20)
# First two cars.
puts Car.cars_by_attrs(cars, mass: 10)
# 3rd car.
# puts Car.cars_by_attrs(cars, new: 10)
# Error !
# puts Car.cars_by_attrs(cars, test: 10)
# Error !

Comments

0

If you look up the docs on group_by you'll find that you can give it a block. If you make the block return the subset of attributes you're interested in, that should give you the required result.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.