2

I have the following array

t = [
  {nil => 1, 10 => 2, 16 => 4, 5=> 10},
  {nil => 9, 5 => 2, 17 => 3, 10 => 2},
  {10 => 4, 5 => 9, 17 => 1}
]

how can I get this as result?

{nil => [1,9,0],10 => [2,2,4], 16 => [4,0,0], 5 => [10,2,9], 17=>[0,3,1]}

I've seen that I can use something like this

t.group_by{|h| h['key']}

but I'm not sure if I can put a regexp inside the brackets

Thanks in advance

Javier

EDIT:

Is just want to group by each key of each hash inside the array, if the key is not present then the value is 0 for that hash

JavierQQ23
  • 704
  • 1
  • 8
  • 20
  • i just don't see any pattern here... – phoet Aug 03 '12 at 20:07
  • @phoet well I know that, but here (http://stackoverflow.com/questions/7670043/ruby-group-hashes-by-value-of-key) he could group by the :type key, so maybe I could group by 2 digits key number or nil – JavierQQ23 Aug 03 '12 at 20:09
  • 2
    This `sort` is a little bit crazy, I don't see the pattern either ... can you explain what is the logic to get to `{nil => [1,9,0],10 => [2,2,4], 16 => [4,0,0], 5 => [10,2,9], 17=>[0,3,1]}` ? – Anthony Alberto Aug 03 '12 at 20:11
  • I just want to group by the key value of each hash inside the array :) – JavierQQ23 Aug 03 '12 at 20:13
  • Ok got it, but you also want to add 0 when there's no entrey ... I doubt a function to do that exists ... might have to write it and go through all hashes – Anthony Alberto Aug 03 '12 at 20:31
  • @AnthonyAlberto that is the part that I'm struggling with. – JavierQQ23 Aug 03 '12 at 20:37
  • 1
    i guess if there is a build in function of ruby that does what you want, then i will stop using it, because there is no more use for a human being in programming anymore... – phoet Aug 03 '12 at 20:50
  • @phoet I'm not searching for a built in function, just want to know how solve this – JavierQQ23 Aug 03 '12 at 20:53

3 Answers3

2

How about this one for illegibility:

t = [
  {nil => 1, 10 => 2, 16 => 4, 5=> 10},
  {nil => 9, 5 => 2, 17 => 3, 10 => 2},
  {10 => 4, 5 => 9, 17 => 1}
]

# Create hash of possible keys
keys = t.reduce({}) { |m, h| h.each_key { |k| m[k] = [] }; m }

# Iterate through array, for each hash, for each key, append the 
# value if key is in hash or zero otherwise
t.reduce(keys) { |m, h| m.each_key { |k| m[k] << (h[k] || 0) }; m }

puts keys
#=> {nil=>[1, 9, 0], 10=>[2, 2, 4], 16=>[4, 0, 0], 5=>[10, 2, 9], 17=>[0, 3, 1]}
cyang
  • 5,574
  • 2
  • 25
  • 34
1

I do not think there is any any function available Just gave a try with hash

  def do_my_work(data) 
    hash = {}
    #get all keys first 
    arr.map{|m| m.keys}.flatten.uniq.each {|a| hash[a]=[]}
    # Now iterate and fill the values
    arr.each do |elm|
      hash.each do |k,v|
        hash[k] << (elm[k].nil? ? 0 : elm[k])
      end
    end
  end   

  hash = do_my_work(t)

  puts hash
  # => {nil=>[1, 9, 0], 10=>[2, 2, 4], 16=>[4, 0, 0], 5=>[10, 2, 9], 17=>[0, 3, 1]} 
Pritesh Jain
  • 9,106
  • 4
  • 37
  • 51
  • I try to put the zero on the position that is not present, so as 17 is not part of the first hash it has to show this: 17 => [0,3,1] – JavierQQ23 Aug 03 '12 at 20:55
1

Not the most elegant code I've ever written, but it does the job and is easy to understand:

def jqq(a)
  keys = []
  result = {}

  a.each do |h|
    keys += h.keys
  end

  keys.uniq.each do |key|
    result[key] = []
    a.each do |h|
      h.default = 0
      result[key] << h[key]
    end
  end

  result
end

t = [
  {nil => 1, 10 => 2, 16 => 4, 5=> 10},
  {nil => 9, 5 => 2, 17 => 3, 10 => 2},
  {10 => 4, 5 => 9, 17 => 1}
]

puts jqq(t)
# {nil=>[1, 9, 0], 10=>[2, 2, 4], 16=>[4, 0, 0], 5=>[10, 2, 9], 17=>[0, 3, 1]}
Darshan Rivka Whittle
  • 32,989
  • 7
  • 91
  • 109