public
Description: Ruby on Rails
Homepage: http://rubyonrails.org
Clone URL: git://github.com/rails/rails.git
Add in_groups to ActiveSupport::CoreExtensions::Array::Grouping. [#579 
state:resolved]

Signed-off-by: Pratik Naik <pratiknaik@gmail.com>
xymbol (author)
Mon Jul 14 21:17:03 -0700 2008
lifo (committer)
Tue Jul 15 07:04:26 -0700 2008
commit  fc89a951933638b051bb1f9e1339ee6ae7c94cda
tree    dfef7e73b3b19a65895651c82cb6e0b727394eab
parent  c1531ae00dbd3ac804bce02733e050ec43400607
...
1
2
 
 
 
 
 
 
3
4
5
...
1
2
3
4
5
6
7
8
9
10
11
0
@@ -1,5 +1,11 @@
0
 *Edge*
0
 
0
+* Add Array#in_groups which splits or iterates over the array in specified number of groups. #579. [Adrian Mugnolo] Example:
0
+  
0
+  a = (1..10).to_a
0
+  a.in_groups(3)        #=> [[1, 2, 3, 4], [5, 6, 7, nil], [8, 9, 10, nil]]
0
+  a.in_groups(3, false) #=> [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
0
+
0
 * Fix TimeWithZone unmarshaling: coerce unmarshaled Time instances to utc, because Ruby's marshaling of Time instances doesn't respect the zone [Geoff Buesing]
0
 
0
 * Added Memoizable mixin for caching simple lazy loaded attributes [Josh Peek]
...
4
5
6
7
8
 
 
9
10
11
...
39
40
41
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
42
43
44
...
4
5
6
 
 
7
8
9
10
11
...
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
0
@@ -4,8 +4,8 @@ module ActiveSupport #:nodoc:
0
   module CoreExtensions #:nodoc:
0
     module Array #:nodoc:
0
       module Grouping
0
-        # Iterates over the array in groups of size +number+, padding any remaining 
0
-        # slots with +fill_with+ unless it is +false+.
0
+        # Splits or iterates over the array in groups of size +number+,
0
+        # padding any remaining slots with +fill_with+ unless it is +false+.
0
         # 
0
         #   %w(1 2 3 4 5 6 7).in_groups_of(3) {|g| p g}
0
         #   ["1", "2", "3"]
0
@@ -39,6 +39,49 @@ module ActiveSupport #:nodoc:
0
           end
0
         end
0
 
0
+        # Splits or iterates over the array in +number+ of groups, padding any
0
+        # remaining slots with +fill_with+ unless it is +false+.
0
+        #
0
+        #   %w(1 2 3 4 5 6 7 8 9 10).in_groups(3) {|g| p g}
0
+        #   ["1", "2", "3", "4"]
0
+        #   ["5", "6", "7", nil]
0
+        #   ["8", "9", "10", nil]
0
+        #
0
+        #   %w(1 2 3 4 5 6 7).in_groups(3, '&nbsp;') {|g| p g}
0
+        #   ["1", "2", "3"]
0
+        #   ["4", "5", "&nbsp;"]
0
+        #   ["6", "7", "&nbsp;"]
0
+        #
0
+        #   %w(1 2 3 4 5 6 7).in_groups(3, false) {|g| p g}
0
+        #   ["1", "2", "3"]
0
+        #   ["4", "5"]
0
+        #   ["6", "7"]
0
+        def in_groups(number, fill_with = nil)
0
+          # size / number gives minor group size;
0
+          # size % number gives how many objects need extra accomodation;
0
+          # each group hold either division or division + 1 items.
0
+          division = size / number
0
+          modulo = size % number
0
+
0
+          # create a new array avoiding dup
0
+          groups = []
0
+          start = 0
0
+
0
+          number.times do |index|
0
+            length = division + (modulo > 0 && modulo > index ? 1 : 0)
0
+            padding = fill_with != false &&
1
+              modulo > 0 && length == division ? 1 : 0
0
+            groups << slice(start, length).concat([fill_with] * padding)
0
+            start += length
0
+          end
0
+
0
+          if block_given?
0
+            groups.each{|g| yield(g) }
0
+          else
0
+            groups
0
+          end
0
+        end
0
+
0
         # Divides the array into one or more subarrays based on a delimiting +value+
0
         # or the result of an optional block.
0
         #
...
99
100
101
102
 
103
104
105
...
109
110
111
112
 
113
114
115
...
118
119
120
121
 
122
123
124
...
128
129
130
131
 
132
133
134
...
137
138
139
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
141
142
...
99
100
101
 
102
103
104
105
...
109
110
111
 
112
113
114
115
...
118
119
120
 
121
122
123
124
...
128
129
130
 
131
132
133
134
...
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
0
@@ -99,7 +99,7 @@ class ArrayExtToSTests < Test::Unit::TestCase
0
 end
0
 
0
 class ArrayExtGroupingTests < Test::Unit::TestCase
0
-  def test_group_by_with_perfect_fit
0
+  def test_in_groups_of_with_perfect_fit
0
     groups = []
0
     ('a'..'i').to_a.in_groups_of(3) do |group|
0
       groups << group
0
@@ -109,7 +109,7 @@ class ArrayExtGroupingTests < Test::Unit::TestCase
0
     assert_equal [%w(a b c), %w(d e f), %w(g h i)], ('a'..'i').to_a.in_groups_of(3)
0
   end
0
 
0
-  def test_group_by_with_padding
0
+  def test_in_groups_of_with_padding
0
     groups = []
0
     ('a'..'g').to_a.in_groups_of(3) do |group|
0
       groups << group
0
@@ -118,7 +118,7 @@ class ArrayExtGroupingTests < Test::Unit::TestCase
0
     assert_equal [%w(a b c), %w(d e f), ['g', nil, nil]], groups
0
   end
0
 
0
-  def test_group_by_pads_with_specified_values
0
+  def test_in_groups_of_pads_with_specified_values
0
     groups = []
0
 
0
     ('a'..'g').to_a.in_groups_of(3, 'foo') do |group|
0
@@ -128,7 +128,7 @@ class ArrayExtGroupingTests < Test::Unit::TestCase
0
     assert_equal [%w(a b c), %w(d e f), ['g', 'foo', 'foo']], groups
0
   end
0
 
0
-  def test_group_without_padding
0
+  def test_in_groups_of_without_padding
0
     groups = []
0
 
0
     ('a'..'g').to_a.in_groups_of(3, false) do |group|
0
@@ -137,6 +137,48 @@ class ArrayExtGroupingTests < Test::Unit::TestCase
0
 
0
     assert_equal [%w(a b c), %w(d e f), ['g']], groups
0
   end
0
+
0
+  def test_in_groups_returned_array_size
0
+    array = (1..7).to_a
0
+
0
+    1.upto(array.size + 1) do |number|
0
+      assert_equal number, array.in_groups(number).size
0
+    end
0
+  end
0
+
0
+  def test_in_groups_with_empty_array
0
+    assert_equal [[], [], []], [].in_groups(3)
0
+  end
0
+
0
+  def test_in_groups_with_block
0
+    array = (1..9).to_a
0
+    groups = []
0
+
0
+    array.in_groups(3) do |group|
0
+      groups << group
0
+    end
0
+
0
+    assert_equal array.in_groups(3), groups
0
+  end
0
+
0
+  def test_in_groups_with_perfect_fit
0
+    assert_equal [[1, 2, 3], [4, 5, 6], [7, 8, 9]],
0
+      (1..9).to_a.in_groups(3)
0
+  end
0
+
0
+  def test_in_groups_with_padding
0
+    array = (1..7).to_a
0
+
0
+    assert_equal [[1, 2, 3], [4, 5, nil], [6, 7, nil]],
0
+      array.in_groups(3)
0
+    assert_equal [[1, 2, 3], [4, 5, 'foo'], [6, 7, 'foo']],
0
+      array.in_groups(3, 'foo')
0
+  end
0
+
0
+  def test_in_groups_without_padding
0
+    assert_equal [[1, 2, 3], [4, 5], [6, 7]],
0
+      (1..7).to_a.in_groups(3, false)
0
+  end
0
 end
0
 
0
 class ArraySplitTests < Test::Unit::TestCase

Comments