user11652832
user11652832

Reputation:

Given a hash with an array of values, how to extract numbers of unique values of each key?

I have a hash that has an array of values for each key:

h = {
  'a' => ['c', 'b', 'd'],
  'b' => ['c', 'b', 'f', 'g']
}

I need to return a hash g that gives the number of "unique" values of each key in h. For example, h['a'] has 2 values ('c' and b') that are not unique in the sense that they are present in h['b']. In that case the value of 'a' in g should equal 1 since 'd' is the only unique element of h['a']. The same goes for the key 'b'. It has 2 common values with 'a' in h, but 2 unique ones as well ('f' and g'). So in my case the g should equal {'a' => 1,b=> 2}.

I have tried h.select { |_,a| a.size == 1 }, but it returns an empty hash.

Also, I have a way of returning the unique values but when I'm trying to write the Rspec test it fails, the solution I have is the following:

@split_log_file.each { |key, array|
  "#{key} has #{array.uniq.length} unique visitors" }

Upvotes: 0

Views: 97

Answers (2)

Praveen
Praveen

Reputation: 250

Below code would work with more than two keys also

h = {
  'a' => ['c', 'b', 'd'],
  'b' => ['c', 'b', 'f', 'g']
}
g={}

all_values = h.values.flatten
uniq_elements = all_values.select{|element| all_values.count(element) == 1 }
h.each do |k,v|
  g[k] = (v & uniq_elements).count
end
g

If we don't want to check duplicates in self array of hash then we can collect uniq like below

h = { 'cat' => ['c', 'b', 'd', 'c', 'e', 'f'],
      'dog' => ['c', 'b', 'f', 'g'],
      'pig' => ['h', 'h', 'b', 'f'] }

g={}

all_values = h.values.collect{|val| val.uniq}.flatten
uniq_elements = all_values.select{|element| all_values.count(element) == 1 }
h.each do |k,v|
  g[k] = (v & uniq_elements).count
end
g

Upvotes: 1

Cary Swoveland
Cary Swoveland

Reputation: 110685

This should meet your requirements.

def uniqify(h)
  keys = h.keys
  keys.each_with_object({}) { |k,g| g[k] =
    (keys-[k]).reduce(h[k]) { |a,kk| a-h[kk] }.uniq.size } }
end

h = { 'cat' => ['c', 'b', 'e', 'f', 'c'],
      'dog' => ['c', 'b', 'f', 'g', 'h'] }

uniqify h
  #=> {"cat"=>1, "dog"=>2}

h = { 'cat' => ['c', 'b', 'd', 'c', 'e', 'f'],
      'dog' => ['c', 'b', 'f', 'g'],
      'pig' => ['h', 'h', 'b', 'f'] }

uniqify h
  #=> {"cat"=>2, "dog"=>1, "pig"=>1}

See Array#-.

Upvotes: 2

Related Questions