Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Podium Style Sorting in Ruby

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: "..." }
]

enter image description here

like image 856
Kyle Decot Avatar asked Oct 30 '13 16:10

Kyle Decot


3 Answers

arr.sort_by{|a| a['created_at']}.inject([]){ |r, e| r.reverse << e }

Fun problem!

like image 67
bonzofenix Avatar answered Nov 10 '22 23:11

bonzofenix


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
like image 6
agmin Avatar answered Nov 10 '22 23:11

agmin


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}]
like image 5
Aaron Cronin Avatar answered Nov 11 '22 01:11

Aaron Cronin