Home > Back-end >  Transforming hash values based on condition after using group_by
Transforming hash values based on condition after using group_by

Time:12-16

I have an array of pipes which have the following attributes: pipe_id grade and grade_confidence.

I am looking to find objects within an array that have the same attributes as other objects with the same ID. I have been using group_by and transform_values to find the IDs that have only one grade - that works fine (thanks to answers in Using group_by for only certain attributes). However I would still like to keep the grade_confidence in the final result if possible.

class Pipes
  attr_accessor :pipe_id, :grade, :grade_confidence
  def initialize(pipe_id, grade, grade_confidence)
    @pipe_id = pipe_id
    @grade = grade
    @grade_confidence = grade_confidence
  end
end

pipe1 = Pipes.new("10001", "60", "A")
pipe2 = Pipes.new("10001", "60", "A")
pipe3 = Pipes.new("10001", "3", "F")
pipe4 = Pipes.new("1005", "15", "A")
pipe5 = Pipes.new("1004", "40", "A")
pipe6 = Pipes.new("1004", "40", "B")

pipes = []
pipes.push(pipe1, pipe2, pipe3, pipe4, pipe5, pipe6)

# We now have our array of pipe objects.

non_dups = pipes.group_by(&:pipe_id).transform_values { |a| a.map(&:grade).uniq }.select { |k,v| v.size == 1 }

puts non_dups

# => {"1005"=>["15"], "1004"=>["40"]}

Desired

The above does what I want - as "10001" has two different grades, it is ignored, and "1004" and "1005" have the same grades per ID. But what I would like is to keep the grade_confidence too, or include grade_confidence based on a condition also.

E.g. If grade_confidence is == "B" the final result would be # => {"1004"=>["40", "B"]}

or

If grade_confidence is == "A" the final result would be # => {"1005"=>["15", "A"], "1004"=>["40", "A"]}

Is it possible to tweak the transform_values to allow this or would I need to go another route?

Thanks

CodePudding user response:

You need to update it:

non_dups = pipes
  .group_by(&:pipe_id)
  .transform_values { |a| [a.map(&:grade).uniq, a.map(&:grade_confidence)]}
  .select { |_, (grades, _confidences)| grades.size == 1 }
  .transform_values {|grades, confindeces| [grades.first, confindeces.sort.first]}
  • Related