-1

I have a data pair:

[{:mobile=>21, :web=>43},{:mobile=>23, :web=>543},{:mobile=>23, :web=>430},{:mobile=>34, :web=>13},{:mobile=>26, :web=>893}]

How can I make this into:

[{mobile: [21, 23, 34, 26]}, {web: [43, 543, 430, 13, 893]}
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Sudhir Vishwakarma
  • 785
  • 10
  • 15
  • 1
    Welcome to SO! We'd like to see evidence of your effort to solve this. Please see "[ask]", "[Stack Overflow question checklist](https://meta.stackoverflow.com/questions/260648)" and "[MCVE](https://stackoverflow.com/help/minimal-reproducible-example)" and all their linked pages. Without code, or where you've searched, it looks like you didn't try and want us to write code for you, which is off-topic. Instead, show us the absolute minimal example of code that demonstrates what you tried, and why it didn't work. – the Tin Man Apr 29 '20 at 05:16
  • Thanks, @theTinMan, I will walk my self through the links, next time I post a question. – Sudhir Vishwakarma Apr 29 '20 at 10:20
  • What is the code you are having trouble with? What trouble do you have with your code? Do you get an error message? What is the error message? Is the result you are getting not the result you are expecting? What result do you expect and why, what is the result you are getting and how do the two differ? Is the behavior you are observing not the desired behavior? What is the desired behavior and why, what is the observed behavior, and in what way do they differ? Please, provide a [mre]. Please be aware that [so] is not a code-writing service, you need to show your efforts! – Jörg W Mittag Apr 30 '20 at 06:37

1 Answers1

2

When I look at the provide scenario I see the following solution:

data = [{:mobile=>21, :web=>43},{:mobile=>23, :web=>543},{:mobile=>23, :web=>430},{:mobile=>34, :web=>13},{:mobile=>26, :web=>893}]
keys = [:mobile, :web]
result = keys.zip(data.map { |hash| hash.values_at(*keys) }.transpose).to_h
#=> {:mobile=>[21, 23, 23, 34, 26], :web=>[43, 543, 430, 13, 893]}

This first extracts the values of the keys from each hash, then transposes the the resulting array. This changes [[21, 43], [23, 543], [23, 430], ...] into [[21, 23, 23, ...], [43, 543, 430, ...]]. This result can be zipped back to the keys and converted into a hash.

To get rid of duplicates you could add .each(&:uniq!) after the transpose call, or map the collections to a set .map(&:to_set) (you need to require 'set') if you don't mind the values being sets instead of arrays.

result = keys.zip(data.map { |hash| hash.values_at(*keys) }.transpose.each(&:uniq!)).to_h
#=> {:mobile=>[21, 23, 34, 26], :web=>[43, 543, 430, 13, 893]}

require 'set'
result = keys.zip(data.map { |hash| hash.values_at(*keys) }.transpose.map(&:to_set)).to_h
#=> {:mobile=>#<Set: {21, 23, 34, 26}>, :web=>#<Set: {43, 543, 430, 13, 893}>}

References:

3limin4t0r
  • 19,353
  • 2
  • 31
  • 52