Given that I have array of hashes, how can I sort them (using ruby) into a podium style (using their created_at value) like in the image below?
[
{ created_at: "DATETIME", src: "..." },
{ created_at: "DATETIME", src: "..." },
{ created_at: "DATETIME", src: "..." },
{ created_at: "DATETIME", src: "..." }
]
arr.sort_by{|a| a['created_at']}.inject([]){ |r, e| r.reverse << e }
Fun problem!
I'm sure you could compress this further, but something like this would do the trick:
# Your initial array
item_array = [{...}]
count = 0
# Sort it first, then stagger results to each side of the array
podium_sorted = item_array.sort_by{|a| a['created_at']}.inject([]) do |arr, item|
count += 1
count % 2 == 0 ? arr.unshift(item) : arr.push(item)
end
If you aren't averse to using a completely mental solution, I quite like this one:
zipped = (1..5).zip [:push, :unshift].cycle
# => [[1, :push], [2, :unshift], [3, :push], [4, :unshift], [5, :push]]
[].tap { |result| zipped.each { |val, op| result.send op, val } }
# => [4, 2, 1, 3, 5]
module Enumerable
def to_podium
[].tap { |r| (zip [:push, :unshift].cycle).each { |v, o| r.send o, v } }
end
end
(1..10).to_podium
# => [10, 8, 6, 4, 2, 1, 3, 5, 7, 9]
And showing it in action:
test_input = (1..5).map { |i| { created_at: i, some_val: rand(100) } }.shuffle
# => [{:created_at=>3, :some_val=>69},
# {:created_at=>5, :some_val=>15},
# {:created_at=>2, :some_val=>89},
# {:created_at=>4, :some_val=>77},
# {:created_at=>1, :some_val=>54}]
test_input.sort_by { |e| e[:created_at] }.to_podium
# => [{:created_at=>4, :some_val=>77},
# {:created_at=>2, :some_val=>89},
# {:created_at=>1, :some_val=>54},
# {:created_at=>3, :some_val=>69},
# {:created_at=>5, :some_val=>15}]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With