简体   繁体   中英

Sum the values for all similar hash keys Ruby

Below is my code. It works (yes!), but it requires 3 loops (yikes!). Still new to coding, but I am wondering if there is a more efficient, dryer, or simply better looking way of producing the desired result. The goal is to sum the values for all similar car makes. I then store the values in a hash for each make ({"Honda" => 12400}) and then store the hashes within an array. Not sure if this is the best way to go about it, but assume down the line you will want to access the values depending on the make. I also want to avoid hard coding anything - assume there are 100 different makes. All advice welcome!

    cars = [
  {
    make: "Nissan",
    model: "Model",
    year: 2017,
    value: 5000
  },
  {
    make: "Toyota",
    model: "Corolla",
    year: 1997,
    value: 1000
  },
  {
    make: "Toyota",
    model: "Camry",
    year: 2006,
    value: 3500
  },
  {
  make: "Honda",
  model: "Accord",
  year: 2001,
  value: 5000
  },
  {
    make: "Toyota",
    model: "Tacoma",
    year: 2001,
    value: 2000
  },
  {
    make: "Honda",
    model: "Civic",
    year: 2001,
    value: 1200
  },
  {
    make: "Honda",
    model: "Civic",
    year: 2005,
    value: 2200
  },
  {
    make: "Honda",
    model: "Accord",
    year: 2010,
    value: 4000
  },
  {
    make: "Nissan",
    model: "Altima",
    year: 2017,
    value: 10000
  }
]

#GOAL
#Sum the values for all similar makes and store in an array with a nested hash
# sums_array = [{all_hondas: total_sum}, {all_toyotas: total_sum}]

total_value = 0
car_makes = []
cars.each{|car|
  #creates a hash with a car's make as the key and 0 as the value
  car_hash = {car[:make] => total_value}
  #shovels car_hash into an array if it does not already exist within the array
  unless car_makes.include? car_hash
    car_makes << car_hash
  end
}

values_array = []
car_makes.each {|make|
  make.each {|k, v|
    cars.each{|car|
      if car[:make] == k
        v += car[:value]
      end
    }
    values_array << {k => v}
  }
}

p values_array 

#values_array = [{"Nissan"=>15000}, {"Toyota"=>6500},{"Honda"=>12400}]

Or in one iteration:

cars.each_with_object(Hash.new(0)) { |car, hash| hash[car[:make]] += car[:value] }
#=> {"Nissan"=>15000, "Toyota"=>6500, "Honda"=>12400}

Docs about Enumerable#each_with_object and Hash#new with a default

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM