One Array - 3 Columns of Equal Length

I want to split a single array into 3 columns of equal (or as near to as
possible) length. What would you advise I do?

enjoy!

chewmanfoo wrote:

Ruby on Rails — New in Rails: Enumerable#group_by and Array#in_groups_of

enjoy!

Thank you for your quick response. Sadly, I can’t get this array method
to do what I wish. See below:

<% Category.all.in_groups_of(3, false) do |sorted_categories| %> |
<% for category in sorted_categories %>
<%= link_to category.name, :action => ‘list’, :category => category %>
<% end %>
<% end %>

The above is the code I’m using.

It currently sorts my categories as below:

| Category1 Category2 Category3 | Category4 Category5 Category6 |

This is not what I want. What I want is:

| Category1 | Category4 |
| Category2 | Category5 |
| Category3 | Category6 |

Ruby on Rails — New in Rails: Enumerable#group_by and Array#in_groups_of

enjoy!

This isn’t quite the same thing though.

a = %w(1 2 3 4 5 6 7 8 9 10)

a.in_groups_of(3)
=> [[“1”, “2”, “3”], [“4”, “5”, “6”], [“7”, “8”, “9”], [“10”, nil, nil]]

It gives you 4 groups, not three as the OP’s expecting.

I would use the Array#chunk method at
Jay Fields' Thoughts: Ruby: Array#chunk like this:

a.chunk(3)
=> [[“1”, “4”, “7”, “10”], [“2”, “5”, “8”], [“3”, “6”, “9”]]

Cheers,

Andy

On May 28, 2010, at 9:47 AM, Pale H. wrote:

I want to split a single array into 3 columns of equal (or as near
to as
possible) length. What would you advise I do?

Well, that depends on whether you want the elements to flow row-wise
or column-wise.

irb> require ‘enumerator’
=> true
irb> array = %w[ a b c d e f g h i j k l m n ]
=> [“a”, “b”, “c”, “d”, “e”, “f”, “g”, “h”, “i”, “j”, “k”, “l”, “m”,
“n”]

Row-wise is easy

irb> array.each_slice(3) do |a,b,c|
puts [a,b,c]*’ ’
end
a b c
d e f
g h i
j k l
m n
=> nil

Column-wise is a bit more work

irb> row_count = (array.length + (3-1))/3
=> 5
irb> columns = []
=> []
irb> array.each_slice(row_count) do |col|
columns << col
columns[-1] << nil while columns[-1].length < row_count
end
=> nil
irb> columns.transpose.each do |a,b,c|
puts [a,b,c]*’ ’
end
a f k
b g l
c h m
d i n
e j
=> [[“a”, “f”, “k”], [“b”, “g”, “l”], [“c”, “h”, “m”], [“d”, “i”,
“n”], [“e”, “j”, nil]]

Enjoy!

-Rob

Rob B.
http://agileconsultingllc.com
[email protected]

[email protected]

On 28 May 2010 15:10, Rob B. [email protected] wrote:

irb> row_count = (array.length + (3-1))/3

That looks a little clunky to me… I’d rather use

(array.length / 3.0).ceil

No difference in the result though! :slight_smile:

But the OP’s request is a little vague as people have pointed out -
Should the three groups be ‘shuffled’ (ie one of each of the first
three elements in each column, and one of each of the next three, and
so on…)? or is it the 1st, 2nd, and 3rd third of elements grouped
together? is it three arrays of equal size for use in the controller?
or three columns in a view that’s needed? and if in the view, is it
data that can be presented in an HTML table, or will it be CSS floated
layout elements?

Hopefully though, there’s been enough suggestions and pointers to the
API docs for Enumerable for the OP to get a result :slight_smile:

[…]

Column-wise is a bit more work

irb> row_count = (array.length + (3-1))/3
=> 5
irb> columns = []
=> []
[…]

Why go to all that trouble? in_groups and zip. Done. No arithmetic.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

in_groups and in_groups_of

part of rails api - hadn’t spotted those before and would never have
thought of looking for them.
I often wonder how many other useful little goodies I may be missing.
Always useful to keep an eye on this group.

thanks Marnen

On 31 May 2010 07:16, tonypm [email protected] wrote:

I often wonder how many other useful little goodies I may be missing.

The have a page through the API docs… it’s all in there!

There’s interesting stuff in both the Ruby [1] and Rails [2] APIs.
You’ll learn loads from looking through both resources’ methods for
String, Integer, Array, Enumerable; and in Rails, the
ActionView::Helpers are great eye openers.

[1] http://ruby-doc.org/ - look at the “core api” link for your version
[2] http://api.rubyonrails.org/

Phillip K. wrote:

Marnen Laibow-Koser wrote:

[…]

Column-wise is a bit more work

Â
irb> row_count = (array.length + (3-1))/3
=> 5
irb> columns = []
=> []
[…]
Â
Why go to all that trouble? Â in_groups and zip. Â Done. Â No arithmetic.
Â
Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]
Â
That really depends on what the desired output is.Â

You’re right. Â I assumed the OP wanted the output he said he wanted. :slight_smile:

The OP indicated thatÂ
he was looking for a phone book style sorting, top-to-bottom,Â
left-to-right.

I know that.Â

Â

It currently sorts my categories as below:

| Category1 Category2 Category3 | Category4 Category5 Category6 |

This is not what I want. What I want is:

| Category1 | Category4 |
| Category2 | Category5 |
| Category3 | Category6 |
Â
in_groups doesn’t do exactly that.

I’m aware of that. Â That’s why I suggested in_groups and zip, which
will do exactly what the OP wanted.Â

Please don’t only read half of my solution and claim I’m wrong because
you missed the rest.Â

Best,
–Â
Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Sent from my iPhone

Marnen Laibow-Koser wrote:

[…]

Column-wise is a bit more work

irb> row_count = (array.length + (3-1))/3
=> 5
irb> columns = []
=> []
[…]

Why go to all that trouble? in_groups and zip. Done. No arithmetic.

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

That really depends on what the desired output is. The OP indicated that
he was looking for a phone book style sorting, top-to-bottom,
left-to-right.

It currently sorts my categories as below:

| Category1 Category2 Category3 | Category4 Category5 Category6 |

This is not what I want. What I want is:

| Category1 | Category4 |
| Category2 | Category5 |
| Category3 | Category6 |

in_groups doesn’t do exactly that. Here is an example:

Given a = [1,2,3,4,5,6,7,8,9] and I want the output to be

1 6
2 7
3 8
4 9
5

a = [1,2,3,4,5,6,7,8,9]
=> [1, 2, 3, 4, 5, 6, 7, 8, 9]

a.in_groups(2)
=> [[1, 2, 3, 4, 5], [6, 7, 8, 9, nil]]

a.in_groups_of(2)
=> [[1, 2], [3, 4], [5, 6], [7, 8], [9, nil]]

Here is a method that was constructed back in the Rails 1.2 days [1]:

def in_vertical_groups_of(number, fill_with = nil, &block)
return in_groups_of((size.to_f / number).ceil, fill_with,
&block).transpose
end

a.in_vertical_groups_of(2)
=> [[1, 6], [2, 7], [3, 8], [4, 9], [5, nil]]

I add this to something that is in config/intializers

module ActiveSupport
module CoreExtensions
module Array
module Grouping
def in_vertical_groups_of
end
end
end
end
end

Peace,
Phillip

[1] original thread: In_vertical_groups_of - Rails - Ruby-Forum

Marnen Laibow-Koser wrote:

Phillip K. wrote:

Marnen Laibow-Koser wrote:

[…]

Column-wise is a bit more work

Â
irb> row_count = (array.length + (3-1))/3
=> 5
irb> columns = []
=> []
[…]
Â
Why go to all that trouble? Â in_groups and zip. Â Done. Â No arithmetic.
Â
Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]
Â

I’m aware of that. Â That’s why I suggested in_groups and zip, which
will do exactly what the OP wanted.Â

Please don’t only read half of my solution and claim I’m wrong because
you missed the rest.Â

I didn’t realize “zip” was a reference to a method call. I actually
thought you were making a reference to something speedy. You know, like
“Zip, you’re done.” Since “zip” was followed by “Done”, who was I to
question your placement of a period. For that oversight, I’m terribly
sorry.

Relax.

Peace,
Phillip

Phillip K. wrote:
[…]

I didn’t realize “zip” was a reference to a method call. I actually
thought you were making a reference to something speedy. You know, like
“Zip, you’re done.” Since “zip” was followed by “Done”, who was I to
question your placement of a period. For that oversight, I’m terribly
sorry.

Oh, now I understand the confusion. Yeah, that would do it. :slight_smile:

Relax.

Peace,
Phillip

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

On Jul 15, 2010, at 3:51 PM, Marnen Laibow-Koser wrote:

It currently sorts my categories as below:

I’m aware of that. That’s why I suggested in_groups and zip, which
will do exactly what the OP wanted.

Please don’t only read half of my solution and claim I’m wrong because
you missed the rest.

It would be so much less confusing if you would answer in actual
code rather than just spewing documentation.

-Rob


You received this message because you are subscribed to the Google
Groups “Ruby on Rails: Talk” group.
To post to this group, send email to rubyonrails-
[email protected].
To unsubscribe from this group, send email to [email protected]
.
For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en
.

Rob B.
[email protected] http://AgileConsultingLLC.com/
[email protected] http://GaslightSoftware.com/

On Jul 15, 2010, at 4:29 PM, Marnen Laibow-Koser wrote:

Please don’t only read half of my solution and claim I’m wrong
(as I do not expect others to do it for me), unless the solution is
[email protected]
Your response was quoting a bit of code to which you said “Why go to
all that trouble?” and then mentioned two methods. I think it would
have been better to demonstrate how those two methods would avoid the
“trouble” than to have simply tossed them out.

-Rob

Rob B.
[email protected] http://AgileConsultingLLC.com/
[email protected] http://GaslightSoftware.com/

Rob B. wrote:

On Jul 15, 2010, at 3:51 PM, Marnen Laibow-Koser wrote:

It currently sorts my categories as below:

I’m aware of that. That’s why I suggested in_groups and zip, which
will do exactly what the OP wanted.

Please don’t only read half of my solution and claim I’m wrong because
you missed the rest.

It would be so much less confusing if you would answer in actual
code rather than just spewing documentation.

I told the OP which methods would do the job for him. I didn’t “spew
documentation” as I understand that phrase. I didn’t write code,
either, because I generally don’t like to do that for others on the list
(as I do not expect others to do it for me), unless the solution is
fairly complex and/or unintuitive. In this case, I don’t really think
it was.

-Rob

Best,

Marnen Laibow-Koser
http://www.marnen.org
[email protected]

Rob B. wrote:

On Jul 15, 2010, at 4:29 PM, Marnen Laibow-Koser wrote:

Please don’t only read half of my solution and claim I’m wrong
(as I do not expect others to do it for me), unless the solution is
[email protected]
Your response was quoting a bit of code to which you said “Why go to
all that trouble?” and then mentioned two methods. I think it would
have been better to demonstrate how those two methods would avoid the
“trouble” than to have simply tossed them out.

Again, I’m sorry if it was confusing. I think I was pressed for time
when I responded, and anyhow, there are only a couple of ways one could
combine the two methods, so I didn’t think further explanation was
necessary. Perhaps I misjudged it.

-Rob

Best,

Marnen Laibow-Koser
http;//www.marnen.org
[email protected]