-1

I have been staring at the following array of arrays for a few hours now and any combination of merge, select, find, map, flatten, etc., has not been able to help me yet.

I created some ugly nested loops, but nothing coming close to the Ruby way.

I have an array of arrays:

[
["Ja", nil, "Bijna", nil, "Ja"],
["Nee", nil, "Nee", "Ja", "Nee"],
[nil, nil, "Bijna", "Nee", "Nee"],
["Ja", nil, nil, "Nee", "Ja"],
["Bijna", nil, "Bijna", "Nee", "Ja"]
]

I need to count all the instances of the values vertically, yielding a hash of hashes like this:

{
{"Ja" => 2, "Nee" => 2, => "Bijna" => 1, "nil" => 1},
{"Ja" => 0, "Nee" => 0, => "Bijna" => 0, "nil" => 5}, 
{"Ja" => 0, "Nee" => 1, => "Bijna" => 3, "nil" => 1}, 
{"Ja" => 0, "Nee" => 1, => "Bijna" => 3, "nil" => 1},
{"Ja" => 3, "Nee" => 2, => "Bijna" => 0, "nil" => 0}
}

Please note that each horizontal in the hash is the count of the vertical in the array.

Yielding a new array of arrays (of arrays) is also acceptable, although I like the hash better:

[
[["Ja", 2], ["Nee", 2], ["Bijna", 1], ["nil", 1]],
[[etc]]
]
the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Corstiaan
  • 1,114
  • 15
  • 34
  • 1
    Welcome to SO. Please read "[ask]" and "[mcve]", along with http://meta.stackoverflow.com/q/261592/128421. It looks like you're asking us to write code for you because you don't show us what you tried and what's wrong with it. It's better for us to see your code so we can either fix it or show you where you went wrong. – the Tin Man Dec 02 '16 at 21:21
  • Please down vote this one as well then: http://stackoverflow.com/questions/569694/count-duplicate-elements-in-ruby-array ;-). I didn't add my code because it was boring and won't add anything to the question. Any one who spend more than 1 day with Ruby will know the meaning of .map, .select, .flatten, etc and how it relates to the question. That said, I will take your comment into account moving forward. Thank you as well for the edits to the question. – Corstiaan Dec 02 '16 at 21:26
  • Existing questions, especially legacy questions and especially ones almost 8 years old, show similar and worse problems but that doesn't reduce the need to meet the current goals and guidelines of the site. The site evolves and we try to keep up with new incoming questions and fix old ones. It's expected you'll try to follow the guidelines in place when you ask, not look for justification in the past. – the Tin Man Dec 02 '16 at 21:32
  • Fair enough, that makes sense. I would appreciate some help though, regarding my question. Can you help me figure this out? – Corstiaan Dec 02 '16 at 21:36

3 Answers3

2

Let a be your big array.

values = a.flatten.uniq
all_values_hash = Hash[values.zip([0] * values.count)]
a.transpose.map do |arr| 
  arr.each_with_object(Hash.new(0)) { |item, hash| hash[item] += 1 }          
end.map { |h| all_values_hash.merge(h) }
Ursus
  • 29,643
  • 3
  • 33
  • 50
1
arr = [
  ["Ja",    nil,  "Bijna",    nil,  "Ja"],
  ["Nee",   nil,    "Nee",   "Ja", "Nee"],
  [nil,     nil,  "Bijna",  "Nee", "Nee"],
  ["Ja",    nil,      nil,  "Nee",  "Ja"],
  ["Bijna", nil,  "Bijna",  "Nee",  "Ja"]
]

keys = arr.flatten.uniq
  #=> ["Ja", nil, "Bijna", "Nee"] 
arr.transpose.map { |col| col.each_with_object(keys.product([0]).to_h) { |e,h|
  h[e] += 1 } }
  #=> [{"Ja"=>2, nil=>1, "Bijna"=>1, "Nee"=>1},
  #    {"Ja"=>0, nil=>5, "Bijna"=>0, "Nee"=>0},
  #    {"Ja"=>0, nil=>1, "Bijna"=>3, "Nee"=>1},
  #    {"Ja"=>1, nil=>1, "Bijna"=>0, "Nee"=>3},
  #    {"Ja"=>3, nil=>0, "Bijna"=>0, "Nee"=>2}] 

Note:

arr.transpose
  #=> [["Ja",    "Nee",     nil,  "Ja", "Bijna"],
  #    [nil,       nil,     nil,   nil,     nil],
  #    ["Bijna", "Nee", "Bijna",   nil, "Bijna"],
  #    [nil,      "Ja",   "Nee", "Nee",   "Nee"],
  #    ["Ja",    "Nee",   "Nee",  "Ja",    "Ja"]] 
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100
1

Similar to the other solutions but logic reversed. I find it easier to read.

keys = my_array.flatten.uniq

final_result = my_array.transpose.map do |array|
 keys.each_with_object(Hash.new) do |key,result|
    result[key] = array.count(key)
 end
end
hirolau
  • 13,451
  • 8
  • 35
  • 47