1

IN my ruby script, I have an array of hashes like

arr[{acnt=>"001"},{acnt=>"001"},{acnt=>"002"},{acnt=>"002"},{acnt=>"003"}]

I'd like to count the number based on each account so that the output would be like:

output[{"001"=>2}, {"002"=>2}, {"003"=>1}]

how should I do?

thanks, Jon

4
  • 2
    Wouldn't it be better to have a single Hash {'001' => 2, '002' => 2, '003' => 3} than an array of Hashes? i.e.: arr.each_with_object({}) {|i, o| o[i[:acnt]] = (o[i[:acnt]] || 0) + 1} Commented Dec 3, 2015 at 3:16
  • 1
    @Myst You could do that a bit cleaner if your Hash had a default value: arr.flat_map(&:values).each_with_object(Hash.new(0)) { |v, h| h[v] += 1 }. Commented Dec 3, 2015 at 5:00
  • @muistooshort - I love it 👍🏻 :) Commented Dec 3, 2015 at 5:27
  • @muistooshort and Myst, thanks! Actually my original hash object has other attributes. I used "acnt" only for the sake of simplicity, so i need to specify the attribute hence Myst's way works for me. Commented Dec 3, 2015 at 14:23

2 Answers 2

2

Edit: I just noticed @muistooshort's comment, in which he suggested the same thing that I have except for the (simple) final step (map { |k,v| { k=>v } }). μ, if you wish to post an answer, I'll delete mine.

There are many ways to do this. Here is one:

arr = [{ "acnt"=>"001" }, { "acnt"=>"001" }, { "acnt"=>"002" },
       { "acnt"=>"002" }, { "acnt"=>"003"}]

arr.flat_map(&:values).
    each_with_object(Hash.new(0)) { |s,h| h[s] += 1 }.
    map { |k,v| { k=>v } }
  #=> [{"001"=>2}, {"002"=>2}, {"003"=>1}]

The steps are as follows:

a = arr.flat_map(&:values)
  #=> ["001", "001", "002", "002", "003"] 
h = a.each_with_object(Hash.new(0)) { |s,h| h[s] += 1 }
  #=> {"001"=>2, "002"=>2, "003"=>1} 
h.map { |k,v| { k=>v } }
  #=> [{"001"=>2}, {"002"=>2}, {"003"=>1}] 
Sign up to request clarification or add additional context in comments.

1 Comment

No worries, flat_map and each_with_object is a pretty natural way to go about this.
1

Try the following:

arr = [{acnt: "001"},{acnt: "001"},{acnt: "002"},{acnt: "002"},{acnt: "003"}]
arr.group_by{ |g| g[:acnt]}.map{ |k, v| {k => v.count} }

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.