1

Here is my array:

sorted_array = [["Friday", "42", 8], ["Friday", "34", 8], ["Friday", "41", 78], ["Friday", "35", 7], ["Friday", "40", 7], ["Friday", "36", 6], ["Friday", "39", 7], ["Friday", "37", 56], ["Friday", "38", 6], ["Monday", "38", 3], ["Monday", "39", 5], ["Monday", "37", 54], ["Monday", "40", 6], ["Monday", "36", 6], ["Monday", "41", 7], ["Monday", "35", 7], ["Monday", "42", 7], ["Monday", "34", 8]]

I need to make:

{ 'Friday' => [ ["42", 8], ["34", 8], ["41", 78], ["35", 7], [ "40", 7], ["36", 6], [ "39", 7], ["37", 56], [ "38", 6] ]  }

The same with "Monday".Can someone shed a light on this?

This is how I get the data from POST:

{"0"=>{"Monday"=>{"34"=>8}, "Friday"=>{"34"=>8}}, "1"=>{"Monday"=>{"35"=>7}, "Friday"=>{"35"=>7}}, "2"=>{"Monday"=>{"36"=>6}, "Friday"=>{"36"=>6}}, "3"=>{"Monday"=>{"37"=>54}, "Friday"=>{"37"=>56}}, "4"=>{"Monday"=>{"38"=>3}, "Friday"=>{"38"=>6}}, "5"=>{"Monday"=>{"39"=>5}, "Friday"=>{"39"=>7}}, "6"=>{"Monday"=>{"40"=>6}, "Friday"=>{"40"=>7}}, "7"=>{"Monday"=>{"41"=>7}, "Friday"=>{"41"=>78}}, "8"=>{"Monday"=>{"42"=>7}, "Friday"=>{"42"=>8}}}

Then I turn it into array and sorted:

 hash_array = []
 specific_ranges.each do |key, value|
   value.each do |day, scores|
      scores.each do |a_score, amount|
         hash_array.push [day, a_score, amount]
      end
   end
 end

Sorted:

sorted_array = hash_array.sort_by &:first

7 Answers 7

5

Ruby MAGIC:

p sorted_array.group_by(&:shift) #=> {"Friday"=>[["42", 8], ["34", 8], ["41", 78], ["35", 7] ...

Explanation: shift gets the first value of the array and at the same time removes it from the array, so the group_by function produce exactly what you are looking for.

Sign up to request clarification or add additional context in comments.

1 Comment

Yes. This is lovely, you cleaver cookie. Thanks mate.
2

you can try something like this directly to your data:

data = {"0"=>{"Monday"=>{"34"=>8}, "Friday"=>{"34"=>8}}, "1"=>{"Monday"=>{"35"=>7}, "Friday"=>{"35"=>7}}, "2"=>{"Monday"=>{"36"=>6}, "Friday"=>{"36"=>6}}, "3"=>{"Monday"=>{"37"=>54}, "Friday"=>{"37"=>56}}, "4"=>{"Monday"=>{"38"=>3}, "Friday"=>{"38"=>6}}, "5"=>{"Monday"=>{"39"=>5}, "Friday"=>{"39"=>7}}, "6"=>{"Monday"=>{"40"=>6}, "Friday"=>{"40"=>7}}, "7"=>{"Monday"=>{"41"=>7}, "Friday"=>{"41"=>78}}, "8"=>{"Monday"=>{"42"=>7}, "Friday"=>{"42"=>8}}}

a ||= Hash.new { |h, k| h[k] = [] }   
data.each{ |d|
  d[1].keys.each { |key|
    a[key] << d[1][key]
  }
}

a
# => {"Monday"=>[{"34"=>8}, {"35"=>7}, {"36"=>6}, {"37"=>54}, {"38"=>3}, {"39"=>5}, {"40"=>6}, {"41"=>7}, {"42"=>7}], "Friday"=>[{"34"=>8}, {"35"=>7}, {"36"=>6}, {"37"=>56}, {"38"=>6}, {"39"=>7}, {"40"=>7}, {"41"=>78}, {"42"=>8}]}

You can improve the result further by using Array#uniq for array of hashes if required.

Comments

1
 sorted_array.group_by(&:first).map { |k, v| [k, v.map { |a| a[1..-1] }] }.to_h
 # {"Friday"=>[["42", 8], ["34", 8], ["41", 78], ["35", 7], ["40", 7], ["36", 6], ["39", 7], ["37", 56], ["38", 6]],
 #  "Monday"=>[["38", 3], ["39", 5], ["37", 54], ["40", 6], ["36", 6], ["41", 7], ["35", 7], ["42", 7], ["34", 8]]} 

Comments

1
h = sorted_array.group_by(&:first).each_value{|a| a.each(&:shift)}

h.select{|k, _| k == "Friday"}
#=> { 'Friday' => [ ["42", 8], ["34", 8], ["41", 78], ["35", 7], [ "40", 7], ["36", 6], [ "39", 7], ["37", 56], [ "38", 6] ]  }

Comments

0

I have a quick solution for you. This may not be the optimal but here it is:

sorted_array = [["Friday", "42", 8], ["Friday", "34", 8], ["Friday", "41", 78], ["Friday", "35", 7], ["Friday", "40", 7], ["Friday", "36", 6], ["Friday", "39", 7], ["Friday", "37", 56], ["Friday", "38", 6], ["Monday", "38", 3], ["Monday", "39", 5], ["Monday", "37", 54], ["Monday", "40", 6], ["Monday", "36", 6], ["Monday", "41", 7], ["Monday", "35", 7], ["Monday", "42", 7], ["Monday", "34", 8]]

s = sorted_array.select{|x| x[0] == 'Friday'}.each{|a| a.shift}

Hash['Friday', s]

This will return the result as you require. But while doing it I found a limitation that the line of code:

s = sorted_array.select{|x| x[0] == 'Friday'}.each{|a| a.shift}

is running just a single time and it will return a blank array if you run it the second time consecutively. So if you use this please take care of that. Hope this helps.

Comments

0

This is a standard task for Array#reduce.

sorted_array.reduce({}) { |memo, e| 
  (memo[e.first] ||= []) << e[1..-1]
  memo 
}

Here we fulfill the hash with the rest of every array element, using first elements as keys.

UPD Actually, you don’t need to reorganize your hash, everything might be done within one step:

h = {"0"=>{"Monday"=>{"34"=>8}, "Friday"=>{"34"=>8}}, "1"=>{"Monday"=>{"35"=>7}, "Friday"=>{"35"=>7}}, "2"=>{"Monday"=>{"36"=>6}, "Friday"=>{"36"=>6}}, "3"=>{"Monday"=>{"37"=>54}, "Friday"=>{"37"=>56}}, "4"=>{"Monday"=>{"38"=>3}, "Friday"=>{"38"=>6}}, "5"=>{"Monday"=>{"39"=>5}, "Friday"=>{"39"=>7}}, "6"=>{"Monday"=>{"40"=>6}, "Friday"=>{"40"=>7}}, "7"=>{"Monday"=>{"41"=>7}, "Friday"=>{"41"=>78}}, "8"=>{"Monday"=>{"42"=>7}, "Friday"=>{"42"=>8}}}
h.reduce({}) { |memo, k| 
  k.last.each { |k,v| (memo[k] ||= []) << v.to_a.flatten }
  memo 
}

Comments

0

Two for the price of one:

#1

arr.each_with_object({}) { |a,h| h.update(a.shift=>[a]) { |_,o,n| o+n } }

#2

h = arr.group_by(&:first)
h.each { |k,v| h[k] = v.transpose[1..-1].transpose }

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.