<% col_size = (friends.size/4.0).ceil %>
<% friends.in_groups_of(col_size, false) do |group| %>
<div class=‘list‘>
<ul>
<% group.each do |friend| %>
<li><%= display friend %></li>
<% end %>
</ul>
</div>
<% end %>
Refactorings
No refactoring yet !
Jeremy Weiskotten
November 28, 2007, November 28, 2007 16:21, permalink
You seem to be specifying three different expected results for an array of 9 friends. Which is correct?
[1,2,3],[4,5,6],[7,8,9],[]
[1,2,3],[4,5],[6,7],[8,9]
[1,2,3],[4,5,6],[7,8],[9,10]
Any of these should be pretty easy to do, but the requirements aren't clear.
Jason Dew
November 28, 2007, November 28, 2007 17:23, permalink
here's my first shot at it
class Array
def in_uniform_groups_of(group_count)
answer = Array.new
index = 0
self.class.uniform_partition_sizes(self.size, group_count).each do |size|
answer << self.slice( index, size )
index += size
end
answer
end
def self.uniform_partition_sizes(size, partitions)
answer = Array.new( partitions, size / partitions )
index = 0
total = (size / partitions) * partitions
while total < size
answer[index] += 1
index = (index + 1) % partitions
total += 1
end
answer
end
end
puts (1..9).to_a.in_uniform_groups_of(4).inspect
puts (1..10).to_a.in_uniform_groups_of(4).inspect
JohnnyBusca
November 28, 2007, November 28, 2007 20:57, permalink
The example shown above returned:
9 friends: [1,2,3],[4,5,6],[7,8,9],[]
10 friends: [1,2,3],[4,5,6],[7,8,9],[10]
and I wanted the following:
9 friends: [1,2,3],[4,5],[6,7],[8,9]
10 friends: [1,2,3],[4,5,6],[7,8],[9,10]
In the meantime I've come up with an helper method which works as a wanted.
def split_in_groups(values, cols=4)
cols.downto(1) do |col|
group_size = (values.size / col.to_f).ceil - 1
yield(group = values[0..group_size])
values -= group
end
end
Jeremy Weiskotten
November 28, 2007, November 28, 2007 22:20, permalink
I misread your original post. Now I understand what you're expecting.
I'll post something in a bit.
Jeremy Weiskotten
November 28, 2007, November 28, 2007 23:11, permalink
I've added a columnize method to Array. The unit test confirms that 1-9 and 1-10 in 4 columns behave the way you expect. I think this will work for any other combo. I'm not sure what the behavior should be if there aren't enough items in the array to populate the given number of columns -- in this implementation the method will return an array with only as many columns as necessary, but it would be pretty easy to have it return empty or nil columns instead.
This should be more efficient than the helper you posted above, because it's not resizing the (potentially large) array as you do with "values -= group". It does all of its work with some simple arithmetic to calculate offset and column size for slicing out of the source array.
Please rate this refactoring if it helps!
class Array
def columnize(n_columns)
columns = []
remaining_size = self.size
n_columns.times do |column_idx|
column_size = (remaining_size.to_f / (n_columns - column_idx)).ceil
break if column_size == 0
columns << self.slice(self.size - remaining_size, column_size)
remaining_size -= column_size
end
columns
end
end
class ColumnizeTest < Test::Unit::TestCase
def test_columnize_9
assert_equal [[1,2,3],[4,5],[6,7],[8,9]], (1..9).to_a.columnize(4)
end
def test_columnize_10
assert_equal [[1,2,3],[4,5,6],[7,8],[9,10]], (1..10).to_a.columnize(4)
end
end
I would like to have a piece of code which splits an array in a fixed number of groups.
On a page I have 4 colums. I want to display an array of friends in 4 columns.
On http://skwpspace.com/2006/09/27/multi-column-lists-using-in_groups_of/ I found an example with in_groups_of, but this doesn't do the trick.
An array with 9 friends will result in 3 groups of 3 friends each. [1,2,3],[4,5,6],[7,8,9],[]
and 10 friends will result in 4 groups [1,2,3],[4,5,6],[7,8,9],[10]
And I wanted the results to be: 9: [1,2,3],[4,5],[6,7],[8,9] and [1,2,3],[4,5,6],[7,8],[9,10]
Is there an easy why of getting this?