开发者

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)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜