The desired return value can be obtained as follows.
conflicts.transform_values do |c_resps|
users.each_with_object([]) do |(user,user_resps),c_users|
c_users << user if (c_resps & user_resps) == c_resps
end.tap { |c_users| c_users.replace(['nill']) if c_users.empty? }
end
#=> {"c1"=>["user1", "user2"], "c2"=>["user1", "user2"],
# "c3"=>["user1", "user2", "user3"], "c4"=>["nill"]}
See Hash#transform_values, Array#& and #tap.
(c_resps & user_resps)
in
c_users << user if (c_resps & user_resps) == c_resps
is an array containing all elements in c_resps
(a value in conflicts
) that are also in user_resps
(a value in users
). Therefore all elements in c_resps
are contained in user_resps
if and only if (c_resps & user_resps) == c_resps
1.
Note that it would be easier (and more Ruby-like) to leave "c4"=>["nill"]
as "c4"=>[]
, in which case .tap { |c_users| c_users.replace(['nill']) if arr1.empty? }
could be removed.
To help you understand what is going on I've reorganized the method slightly and inserted puts
statements to display the values of different objects when the method is run.
conflicts.transform_values do |c_resps|
puts "\nc_resps = #{c_resps}"
c_users = []
users.each do |user,user_resps|
puts " user=#{user}, user_resps=#{user_resps}"
puts " c_resps & user_resps = #{c_resps & user_resps}"
c_users << user if (c_resps & user_resps) == c_resps
puts " c_users after c_users << user if... = #{c_users}"
end
c_users = ['nill'] if c_users.empty?
puts "c_users after c_users = ['nill'] if c_users.empty? = #{c_users}"
c_users
end #=> {"c1"=>["user1", "user2"], "c2"=>["user1", "user2"],
# "c3"=>["user1", "user2", "user3"], "c4"=>["nill"]}
This displays the following.
c_resps = ["resp1", "resp2"]
user=user1, user_resps=["resp1", "resp2", "resp3", "resp4"]
c_resps & user_resps = ["resp1", "resp2"]
c_users after c_users << user if... = ["user1"]
user=user2, user_resps=["resp1", "resp2", "resp3", "resp4"]
c_resps & user_resps = ["resp1", "resp2"]
c_users after c_users << user if... = ["user1", "user2"]
user=user3, user_resps=["resp1", "resp4"]
c_resps & user_resps = ["resp1"]
c_users after c_users << user if... = ["user1", "user2"]
c_users after c_users = ['nill'] if c_users.empty? = ["user1", "user2"]
c_resps = ["resp1", "resp3"]
user=user1, user_resps=["resp1", "resp2", "resp3", "resp4"]
c_resps & user_resps = ["resp1", "resp3"]
c_users after c_users << user if... = ["user1"]
user=user2, user_resps=["resp1", "resp2", "resp3", "resp4"]
c_resps & user_resps = ["resp1", "resp3"]
c_users after c_users << user if... = ["user1", "user2"]
user=user3, user_resps=["resp1", "resp4"]
c_resps & user_resps = ["resp1"]
c_users after c_users << user if... = ["user1", "user2"]
c_users after c_users = ['nill'] if c_users.empty? = ["user1", "user2"]
c_resps = ["resp1", "resp4"]
user=user1, user_resps=["resp1", "resp2", "resp3", "resp4"]
c_resps & user_resps = ["resp1", "resp4"]
c_users after c_users << user if... = ["user1"]
user=user2, user_resps=["resp1", "resp2", "resp3", "resp4"]
c_resps & user_resps = ["resp1", "resp4"]
c_users after c_users << user if... = ["user1", "user2"]
user=user3, user_resps=["resp1", "resp4"]
c_resps & user_resps = ["resp1", "resp4"]
c_users after c_users << user if... = ["user1", "user2", "user3"]
c_users after c_users = ['nill'] if c_users.empty? = ["user1", "user2", "user3"]
c_resps = ["resp3", "resp5", "resp6"]
user=user1, user_resps=["resp1", "resp2", "resp3", "resp4"]
c_resps & user_resps = ["resp3"]
c_users after c_users << user if... = []
user=user2, user_resps=["resp1", "resp2", "resp3", "resp4"]
c_resps & user_resps = ["resp3"]
c_users after c_users << user if... = []
user=user3, user_resps=["resp1", "resp4"]
c_resps & user_resps = []
c_users after c_users << user if... = []
c_users after c_users = ['nill'] if c_users.empty? = ["nill"]
1. (c_resps & v) == c_resps
could be replaced with (among others) (v-c_resps).empty?
or arr1 << k if v.all? { |e| c_resps.include?(e) }
.