1

I have an array full of events with a date field. I wanted to sort the array by the date field, but then after this is sorted, shuffle the events within each day (but still maintaining the date order):

@events = Event.order('date desc').shuffle....?

This is an example of what I want:

Array:

[
  Event 1 (Jan. 2),
  Event 2 (Jan. 1),
  Event 3 (Jan. 3),
  Event 4 (Jan. 1),
  Event 5 (Jan. 3)
]

On one request, I want this order:

Event 2, Event 4, Event 1, Event 3, Event 5

But, on another request, a different random order:

Event 4, Event 2, Event 1, Event 5, Event 3

On each request I want a similar variation that maintains the date order, but shuffles events within each day.

Michael Gaskill
  • 7,913
  • 10
  • 38
  • 43
gitastic
  • 516
  • 7
  • 26
  • when you shuffle, it obvious you lose the ordering right, try doing something like `Event.all.shuffle.sort_by(&:date)` but be aware you query all the events here – Manuel van Rijn May 20 '16 at 21:53
  • yeah, thanks manuel. tried this, but doesn't work because i have conditions before the sort/order. any other suggestions? – gitastic May 20 '16 at 22:04
  • When asking we expect to see evidence of your effort. Without that it looks like you're asking us to write the code for you, which isn't what SO is for. – the Tin Man May 20 '16 at 23:08
  • @ManuelvanRijn That's an interesting suggestion. Ruby's sort is not [stable](http://stackoverflow.com/a/1517824/238886), but I don't know whether that is actually bad in this case. – Wayne Conrad May 20 '16 at 23:31

2 Answers2

2

Try this:

@events = Event.order("date, random()")

This will provide random ordering of the events within the same date.

Michael Gaskill
  • 7,913
  • 10
  • 38
  • 43
  • this seems like exactly what i need, but getting this error: PG::GroupingError: ERROR: column "events.id" must appear in the GROUP BY clause or be used in an aggregate function – gitastic May 20 '16 at 22:14
  • thanks michael for helping out! I tried putting in random(events.id), but getting this error: PG::UndefinedFunction: ERROR: function random(integer) does not exist – gitastic May 20 '16 at 22:28
  • I tried this, and seems to work: Event.group("events.id").order("date, random()") - if you want to edit your answer, i'll accept, you were closest, thx! – gitastic May 20 '16 at 22:44
  • Do you even need the group? – Frederick Cheung May 21 '16 at 07:09
  • @FrederickCheung At this point, probably not. This went through a number of edits, and the group was part of the original solution. Good observation. I'll test it and if it's no longer needed, I can remove the group. Cheers! – Michael Gaskill May 21 '16 at 07:26
1

Assuming events is an enumerable already sorted by date you could do something like

events.chunk {|event| event.date.to_date}.flat_map  do |(_date, elements)|
  elements.shuffle
end

chunk groups consecutive elements for which the block returns the same value. It returns an array of pairs of the chunk value (the return element from the block) and the corresponding array values. Then all you need to do is shuffle those chunks.

Frederick Cheung
  • 83,189
  • 8
  • 152
  • 174