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 grade
s, 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]}