I have a collection of Blog items.
@blogs = Blog.find(:all)
Each blog has a description textfield with some text. What I would like to do is splitting the @blogs objects into 3 divs, but with roughly the same characters in each column.
<div id="left">
#blog1 (653 characters)
</div>
<div id="center">
#blog2 (200 characters)
#blog5 (451 characters)
</div>
<div id="right">
#blog3 (157 characters)
#blog4 (358 characters)
#blog6 (155 characters)
</div>
I can't figure out how to do that without getting really complicated and probably inefficient.
So far I have thought about converting the description field (size) to % of total characters in the @blogs collection, but how do I match/split the elements, so that I get closest to 33% in each 开发者_JAVA百科column - like a super simple tetris game :)
Any thoughts?
Here's a quick hack that isn't perfect, but might get you pretty close. The algorithm is simple:
- Sort items by size.
- Partition items into N bins.
- Resort each bin by date (or other field, per your desired presentation order)
Here's a quick proof of concept:
#!/usr/bin/env ruby
# mock out some simple Blog class for this example
class Blog
attr_accessor :size, :date
def initialize
@size = rand(700) + 100
@date = Time.now + rand(1000)
end
end
# create some mocked data for this example
@blogs = Array.new(10) { Blog.new }
# sort by size
sorted = @blogs.sort_by { |b| b.size }
# bin into NumBins
NumBins = 3
bins = Array.new(NumBins) { Array.new }
@blogs.each_slice(NumBins) do |b|
b.each_with_index { |x,i| bins[i] << x }
end
# sort each bin by date
bins.each do |bloglist|
bloglist.sort_by! { |b| b.date }
end
# output
bins.each_with_index do |bloglist,column|
puts
puts "Column Number: #{column+1}"
bloglist.each do |b|
puts "Blog: Size = #{b.size}, Date = #{b.date}"
end
total = bloglist.inject(0) { |sum,b| sum + b.size }
puts "TOTAL SIZE: #{total}"
end
For more ideas, look up the multiprocessor scheduling problem.
精彩评论