Outputting 'random' records
Table - Contacts
Name Channel
Teejay Friends
John Colleagues
Rick Friends
Carl Business
Vulcan Business
Scott Office
Alex Friends
How do I out put records from this table, 'randomly'. Well, not exactly random
. I should be able to output the records wherein no records with the same Channel
be beside each other.
A record in the `Friends` Channel
A record in the `Colleagues` Channel
A record in the `Business` Channel
A record in开发者_如何学Go the `Office` Channel
A record in the `Friends` Channel
A record in the `Business` Channel
A record in the `Friends` Channel
More Info:
Friend model, Colleague model, Business model, Office model are child models of Contact.
What do you think about this?
[ Friend, Colleague, Business, Office ].each do |klass|
klass.find(:first, :offset => (klass.count * rand).to_i, :limit => 1)
end
This fetches one entry from every child models. This won't be so fast, but works :)
If you need two iterations, you can wrap the whole block into a:
2.times do
end
But be aware of that order of the models is fixed here. If you need that random as well:
prev = nil
10.times do
klass = [ Friend, Colleague, Business, Office ].reject { |k| k == prev }.shuffle.first
p klass.find(:first, :offset => (klass.count * rand).to_i, :limit => 1)
prev = klass
end
Update:
For curiosity I made a small method for that. Keep in mind that you need to replace the RAND()
to RANDOM()
if you're using SQLite. And please check this question as well.
def get_random_items(classes, count)
# collect at least count / 2 random items from each class
items = Hash.new do |hash,klass|
hash[klass] = klass.find(:all, :order => "RAND()", :limit => (count.to_f / 2).ceil)
end
results = []
prev = nil
while (classes.length > 0 && results.length < count) do
klass = classes.shuffle!.pop
item = items[klass].pop
next unless item
classes << prev if prev
prev = (items[klass].length > 0) ? klass : nil
results << item
end
results
end
Usage: get_random_items([ Friend, Colleague, Business, Office ], 10)
精彩评论