augmented_array 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,86 @@
1
+ Author:
2
+ ====
3
+ Niranjan Sarade
4
+
5
+ About Augmented Array:
6
+ ====
7
+ The Ruby Array class is extended with some traversing/iterating methods and you will also be able to get
8
+ and set the individual array elements with indexes as of the indexes were attributes of an array.
9
+
10
+ Example:
11
+ ====
12
+ require 'augmented_array'
13
+
14
+ [nil,1,2,nil,3].nilitems # => 2
15
+
16
+ [1,2,3,4,5].sum # => 15
17
+
18
+ [1,2,3,4,5,6]/1 # => [[1], [2], [3], [4], [5], [6]]
19
+ [1,2,3,4,5,6]/2 # => [[1, 2], [3, 4], [5, 6]]
20
+ [1,2,3,4,5,6]/8 # => [[1, 2, 3, 4, 5, 6]]
21
+ []/2 # => []
22
+
23
+ [1,2,3,4,5].middle # => 3
24
+ [1,2,3,4].middle # => [2, 3]
25
+ [1].middle # => 1
26
+
27
+ ary = [1,2,3]
28
+ ary.first = 20
29
+ ary.first # => 20
30
+
31
+ [1,1.0,"test",{:key => "value"}].describe # => [{1=>"Fixnum"}, {1.0=>"Float"}, {"test"=>"String"}, {{:key=>"value"}=>"Hash"}]
32
+
33
+ ary = [1,2,3]
34
+ ary.last = 20
35
+ ary.last # => 20
36
+
37
+ [1,2,3,4,5].second_last # => 4
38
+ [1].second_last # => nil
39
+
40
+ ary = [1,2,3,4,5]
41
+ ary.alternate # => [[1, 3, 5], [2, 4]]
42
+ ary # => [1,2,3,4,5]
43
+
44
+ ary = [1,2,3,4,5]
45
+ ary.alternate! # => [[1, 3, 5], [2, 4]]
46
+ ary # => [[1, 3, 5], [2, 4]]
47
+
48
+ ary = [1,2,3,4,5,6,7]
49
+ ary.second = 20
50
+ ary.third = 30
51
+ ary.fourth = 40
52
+ ary.fifth = 50
53
+ ary # => [1, 20, 30, 40, 50]
54
+ ary.second # => 20
55
+ ary.third # => 30
56
+ ary._0 = 25
57
+ ary._0 # => 25 # Similar to ary.at(0) or ary.fetch(0)
58
+ ary._1 = 10
59
+ ary._1 # => 10
60
+ ary._11 = 11
61
+ ary # => [25, 10, 30, 40, 50, nil, nil, nil, nil, nil, nil, 11]
62
+
63
+ ary.each_index { |index|
64
+ eval("p ary._#{index}")
65
+ }
66
+
67
+ ary.each_index { |index|
68
+ eval("ary._#{index} = 10")
69
+ }
70
+
71
+ Install:
72
+ ====
73
+ gem install augmented_array
74
+
75
+ (It has been pushed to http://gemcutter.org)
76
+
77
+ OR
78
+
79
+ Download the gem file from http://github.com/NiranjanSarade/augmented_array.git/
80
+ gem install augmented_array-0.0.1.gem
81
+
82
+ Uninstall:
83
+ ====
84
+ gem uninstall augmented_array
85
+
86
+
@@ -0,0 +1,255 @@
1
+ #
2
+ # augmented_array.rb
3
+ #
4
+ # The Ruby Array class is extended with some traversing methods and you will also be able to get and set the
5
+ # individual array elements with indexes as of the indexes were attributes of an array.
6
+ #
7
+
8
+ Array.class_eval do
9
+
10
+ Map = {:second => 1, :third => 2, :fourth => 3, :fifth => 4, :sixth => 5, :seventh => 6, :eighth => 7, :ninth => 8, :tenth => 9}
11
+
12
+ # Returns array of hashes with element as key and its class as value
13
+ #
14
+ # [1,1.0,"test",{:key => "value"}].describe # => [{1=>"Fixnum"}, {1.0=>"Float"}, {"test"=>"String"}, {{:key=>"value"}=>"Hash"}]
15
+ # [1,2,3].describe # => [{1=>"Fixnum"}, {2=>"Fixnum"}, {3=>"Fixnum"}]
16
+ # [[1,2],1].describe # => [{[1, 2]=>"Array"}, {1=>"Fixnum"}]
17
+ # [].describe # => []
18
+ #
19
+ def describe
20
+ ary = []
21
+ each do |element|
22
+ ary << {element => element.class.to_s}
23
+ end
24
+ ary
25
+ end
26
+
27
+ # Returns count of nil items in the array
28
+ #
29
+ # [nil,1,2,nil,3].nilitems # => 2
30
+ # [1,2,3].nilitems # => 0
31
+ # [].nilitems # => 0
32
+ #
33
+ def nilitems
34
+ size - nitems
35
+ end
36
+
37
+ # Returns the sum of all elements in an integer or float array
38
+ #
39
+ # [1,2,3,4,5].sum # => 15
40
+ # [1.1,2.3,4.56].sum # => 7.96
41
+ # [1,2.5,5].sum # => 8.5
42
+ # [].sum # => nil
43
+ # [1,2,"test"].sum # => The array should be either an integer or float array (RuntimeError)
44
+ #
45
+ def sum
46
+ each do |element|
47
+ unless element.nil?
48
+ if !element.kind_of?(Fixnum) and !element.kind_of?(Float)
49
+ raise RuntimeError, "The array should be either an integer or float array"
50
+ end
51
+ end
52
+ end
53
+ sum = 0
54
+ self.inject {|sum, n| n = 0 if n.nil?; sum + n }
55
+ end
56
+
57
+ # Returns a new array by splitting the array into arrays of int divisor elements each
58
+ #
59
+ # [1,2,3,4,5,6]/1 # => [[1], [2], [3], [4], [5], [6]]
60
+ # [1,2,3,4,5,6]/2 # => [[1, 2], [3, 4], [5, 6]]
61
+ # [1,2,3,4,5,6]/3 # => [[1, 2, 3], [4, 5, 6]]
62
+ # [1,2,3,4,5,6]/4 # => [[1, 2, 3, 4], [5, 6]]
63
+ # [1,2,3,4,5,6]/8 # => [[1, 2, 3, 4, 5, 6]]
64
+ # []/2 # => []
65
+ # [1,2,3]/-2 # => Invalid argument -> -2 (ArgumentError)
66
+ # [1,2,3]/0 # => Invalid argument -> 0 (ArgumentError)
67
+ #
68
+ def /(number)
69
+ raise ArgumentError, "Invalid argument -> #{number.inspect}" if !number.kind_of?(Fixnum) or number.zero? or (number < 0)
70
+ divisor = number.to_i
71
+ split, last, start, final_ary = size.div(divisor), size.modulo(divisor), 0, []
72
+ split.times {
73
+ final_ary << self[start, divisor]
74
+ start += divisor
75
+ }
76
+ final_ary << self[start, last] unless last.zero?
77
+ final_ary
78
+ end
79
+
80
+ # Returns middle or central element of the array
81
+ #
82
+ # [1,2,3,4,5].middle # => 3
83
+ # [1,2,3,4].middle # => [2, 3]
84
+ # [1,2,3,4,5,6].middle # => [3, 4]
85
+ # [1].middle # => 1
86
+ # [].middle # => nil
87
+ #
88
+ def middle
89
+ len = self.size
90
+ return nil if len.zero?
91
+ div = len.div(2)
92
+ if len.modulo(2).zero?
93
+ [self[div-1],self[div]]
94
+ else
95
+ self[div]
96
+ end
97
+ end
98
+
99
+ # Sets value of the first element of the array
100
+ #
101
+ # ary = [1,2,3]
102
+ # ary.first = 20
103
+ # ary.first # => 20
104
+ # ary = []
105
+ # ary.first = 10
106
+ # ary.first # => 10
107
+ #
108
+ def first= value
109
+ self[0] = value
110
+ end
111
+
112
+ # Sets value of the last element of the array
113
+ #
114
+ # ary = [1,2,3]
115
+ # ary.last = 20
116
+ # ary.last # => 20
117
+ # ary = []
118
+ # ary.last = 10
119
+ # ary.last # => 10
120
+ #
121
+ def last= value
122
+ return self[size-1] = value if size > 0
123
+ self[0] = value if size == 0
124
+ end
125
+
126
+ # Returns second last element of the array
127
+ #
128
+ # [1,2,3,4,5].second_last # => 4
129
+ # [1].second_last # => nil
130
+ # [].second_last # => nil
131
+ #
132
+ def second_last
133
+ return nil if (size-2) < 0
134
+ self[size-2]
135
+ end
136
+
137
+ # Returns array of alternate elements collected in arrays
138
+ #
139
+ # ary = [1,2,3,4,5]
140
+ # ary.alternate # => [[1, 3, 5], [2, 4]]
141
+ # ary # => [1,2,3,4,5]
142
+ # [1,2,3,4].alternate # => [[1, 3], [2, 4]]
143
+ # [1,2].alternate # => [[1], [2]]
144
+ # [1].alternate # => [[1]]
145
+ # [].alternate # => []
146
+ #
147
+ def alternate
148
+ return [] if size.zero?
149
+ return [[self[0]]] if size == 1
150
+ populate_alternate_arrays
151
+ end
152
+
153
+ # Modifies the array by returning array of alternate elements collected in arrays
154
+ #
155
+ # ary = [1,2,3,4,5]
156
+ # ary.alternate! # => [[1, 3, 5], [2, 4]]
157
+ # ary # => [[1, 3, 5], [2, 4]]
158
+ # [1,2,3,4].alternate! # => [[1, 3], [2, 4]]
159
+ # [1,2].alternate! # => [[1], [2]]
160
+ # [1].alternate! # => [[1]]
161
+ # [].alternate! # => []
162
+ #
163
+ def alternate!
164
+ return self if size.zero?
165
+ first = self[0]
166
+ return self.clear << [first] if size == 1
167
+ ary1, ary2 = populate_alternate_arrays
168
+ self.clear << ary1 << ary2
169
+ end
170
+
171
+ # Returns block call once with iterating the array elements incremented by positive step, passing that array element as a parameter
172
+ #
173
+ # [1,2,3,4,5,6].step_by(2){|x| p x} # => 1 3 5
174
+ # [1,2,3].step_by(1){|x| p x} # => 1 2 3
175
+ # [1,2,3,4].step_by(6){|x| p x} # => 1
176
+ # [1,2].step_by(0){|x| p x} # => Step can't be 0 or negative (ArgumentError)
177
+ # [1,2].step_by(-1){|x| p x} # => Step can't be 0 or negative (ArgumentError)
178
+ # [1.2].step_by(1) # => no block given (LocalJumpError)
179
+ #
180
+ def step_by(n)
181
+ raise ArgumentError, "Step can't be 0 or negative" if n.zero? or n < 0
182
+ 0.step(size-1,n) {|i| yield self[i]}
183
+ end
184
+
185
+ # Sets and gets the 2nd to 10th elements with method invocations like second, third upto tenth on the array
186
+ # Also, sets and retrieves array value at the specified positive index as if the index was its attribute
187
+ #
188
+ # ary = [1,2,3,4,5,6,7]
189
+ # ary.second = 20
190
+ # ary.third = 30
191
+ # ary.fourth = 40
192
+ # ary.fifth = 50
193
+ # ary.sixth = 60
194
+ # ary.seventh = 70
195
+ # ary.eighth = 80
196
+ # ary.ninth = 90
197
+ # ary.tenth = 100
198
+ # ary # => [1, 20, 30, 40, 50, 60, 70, 80, 90, 100]
199
+ # ary.second # => 20
200
+ # ary.third # => 30
201
+ # ary.tenth # => 100
202
+ # ary._0 = 25
203
+ # ary._0 # => 25 # Similar to ary.at(0) or ary.fetch(0)
204
+ # ary._1 = 10
205
+ # ary._1 # => 10
206
+ # ary._15 = 15
207
+ # ary # => [25, 10, 30, 40, 50, 60, 70, 80, 90, 100, nil, nil, nil, nil, nil, 15]
208
+ #
209
+ # ary.t12 # => undefined method `t12'
210
+ # ary._abcd # => undefined method `_abcd'
211
+ # ary._1a # => undefined method `_1a'
212
+ #
213
+ # ary.each_index { |index|
214
+ # eval("p ary._#{index}")
215
+ # }
216
+ #
217
+ # ary.each_index { |index|
218
+ # eval("ary._#{index} = 10")
219
+ # }
220
+ #
221
+ def method_missing(symbol, *args)
222
+ key = symbol.to_s
223
+ setter = symbol.to_s.chop.to_sym
224
+ if Map.include?(symbol)
225
+ self[Map[symbol]]
226
+ elsif Map.include?(setter)
227
+ self[Map[setter]] = args[0]
228
+ elsif key[0,1] == '_' and key[-1,1] == "=" # only positive index
229
+ self[key.chop[1..-1].to_i] = args[0]
230
+ elsif key[0,1] == '_' and is_numeric?(key[1..-1]) # only positive index
231
+ self[key[1..-1].to_i]
232
+ else
233
+ super
234
+ end
235
+ end
236
+
237
+ private
238
+
239
+ def populate_alternate_arrays
240
+ ary1, ary2 = [],[]
241
+ each_index {|index|
242
+ if index.modulo(2).zero?
243
+ ary1 << self[index]
244
+ else
245
+ ary2 << self[index]
246
+ end
247
+ }
248
+ [ary1, ary2]
249
+ end
250
+
251
+ def is_numeric?(s)
252
+ s.to_i.to_s == s || s.to_f.to_s == s
253
+ end
254
+ end
255
+
@@ -0,0 +1,179 @@
1
+ require File.expand_path(File.dirname(__FILE__) + "/../lib/augmented_array")
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+
4
+ describe Array do
5
+
6
+ before(:each) do
7
+ @my_array = [1,2,3,4,5,nil,6,7,8,9,10,nil]
8
+ end
9
+
10
+ it "should return count of nil items in the array " do
11
+ @my_array.nilitems.should == 2
12
+ [].nilitems.should == 0
13
+ [1,2,3].nilitems.should == 0
14
+ end
15
+
16
+ it "should return the sum of all elements in an integer or float array " do
17
+ @my_array.sum.should == 55
18
+ @my_array << 3.5
19
+ @my_array.sum == 58.5
20
+ end
21
+
22
+ it "should throw Runtime error if any of the array elements is other than integer or float" do
23
+ @my_array << "test"
24
+ lambda {@my_array.sum}.should raise_error(RuntimeError, 'The array should be either an integer or float array')
25
+ end
26
+
27
+ it "should return the middle element with odd number of elements in the array" do
28
+ [1,2,3,4,5].middle.should == 3
29
+ end
30
+
31
+ it "should return array of the middle 2 elements with even number of elements in the array" do
32
+ @my_array.middle.should == [nil,6]
33
+ [1,2,3,4].middle.should == [2,3]
34
+ end
35
+
36
+ it "should return the single element as middle element with one element array" do
37
+ [1].middle.should == 1
38
+ end
39
+
40
+ it "should return nil if middle is invoked on an empty array" do
41
+ [].middle.should be_nil
42
+ end
43
+
44
+ it "should return array of hashes with element as key and its class as value when describe is invoked on an array" do
45
+ ary_desc = [1,1.0,"test",{:key => "value"}].describe
46
+ ary_desc.first.should == {1=>'Fixnum'}
47
+ ary_desc[1].should == {1.0=>'Float'}
48
+ ary_desc[2].should == {'test'=>'String'}
49
+ ary_desc[3].has_value?('Hash')
50
+ end
51
+
52
+ it "should return a new array by splitting the array into arrays of int divisor elements each if number of elements are completely divisible by divisor" do
53
+ ary_div = @my_array / 3
54
+ ary_div.size.should == 4
55
+ ary_div.first.should == [1,2,3]
56
+ ary_div.last.should == [9,10,nil]
57
+ end
58
+
59
+ it "should return a new array by splitting the array into arrays of int divisor elements each and remaining elements if number of elements are not completely divisible by divisor" do
60
+ ary_div = @my_array / 5
61
+ ary_div.size.should == 3
62
+ ary_div.first.should == [1,2,3,4,5]
63
+ ary_div.last.should == [10,nil]
64
+ end
65
+
66
+ it "should set the value of the first element of the array when first= invoked on the array" do
67
+ @my_array.first = 20
68
+ @my_array.first.should == 20
69
+ ary = []
70
+ ary.first = 10
71
+ ary.first.should == 10
72
+ end
73
+
74
+ it "should set the value of the last element of the array when last= invoked on the array" do
75
+ @my_array.last = 10
76
+ @my_array.last.should == 10
77
+ ary = []
78
+ ary.last = 5
79
+ ary.last.should == 5
80
+ end
81
+
82
+ it "should set and access the 2nd to 10th elements with method invocations like second, third upto tenth on the array" do
83
+ @my_array.second = 2
84
+ @my_array.second.should == 2
85
+ @my_array.third = 3
86
+ @my_array.third.should == 3
87
+ @my_array.fourth = 4
88
+ @my_array.fourth.should == 4
89
+ @my_array.fifth = 5
90
+ @my_array.fifth.should == 5
91
+ @my_array.sixth = 6
92
+ @my_array.sixth.should == 6
93
+ @my_array.seventh = 7
94
+ @my_array.seventh.should == 7
95
+ @my_array.eighth = 8
96
+ @my_array.eighth.should == 8
97
+ @my_array.ninth = 9
98
+ @my_array.ninth.should == 9
99
+ @my_array.tenth = 10
100
+ @my_array.tenth.should == 10
101
+ end
102
+
103
+ it "should collect alternate elements in different array and return array of those arrays" do
104
+ new_ary = @my_array.alternate
105
+ new_ary.size.should == 2
106
+ new_ary.first.size.should == 6
107
+ new_ary.second.size.should == 6
108
+ @my_array.size.should == 12
109
+ end
110
+
111
+ it "should collect alternate elements in different array and modify the orignal array by adding those arrays" do
112
+ @my_array.alternate!.size.should == 2
113
+ @my_array.size.should == 2
114
+ @my_array.first.size.should == 6
115
+ @my_array.second.size.should == 6
116
+ end
117
+
118
+ it "should return empty array if alternate is invoked on an empty array" do
119
+ [].alternate.size.should == 0
120
+ [].alternate!.size.should == 0
121
+ end
122
+
123
+ it "should return an array with array consisting of one element if alternate is invoked on a single element array" do
124
+ [1].alternate.size.should == 1
125
+ [1].alternate!.first.first == 1
126
+ end
127
+
128
+ it "should set and retrieve array value at the specified positive index as if the index was its attribute" do
129
+ ary = [1,2,3,4,5]
130
+ ary._0 = 20
131
+ ary._0.should == 20
132
+ ary._1 = 10
133
+ ary._1.should == 10
134
+ ary._7 = 30
135
+ ary.size.should == 8
136
+ ary._7.should == 30
137
+ ary._6.should be_nil
138
+ end
139
+
140
+ it "should throw NoMethodError while setting and getting the array value with wrong index as an attribute on the array" do
141
+ lambda {@my_array._abcd}.should raise_error(NoMethodError)
142
+ lambda {@my_array._1abc}.should raise_error(NoMethodError)
143
+ lambda {@my_array.t12}.should raise_error(NoMethodError)
144
+ lambda {@my_array.s23}.should raise_error(NoMethodError)
145
+ end
146
+
147
+
148
+ it "should call block once with traversing the array elements incremented by positive step, passing that array element as a parameter" do
149
+ ary = [1,2,3,4,5,6]
150
+ new_ary = []
151
+ ary.step_by(2){|x| new_ary << x}
152
+ new_ary.should == [1,3,5]
153
+ end
154
+
155
+ it "should call block once with traversing all the elements similar to each method" do
156
+ ary = [1,2,3,4,5,6]
157
+ new_ary = []
158
+ ary.step_by(1) {|x| new_ary << x}
159
+ new_ary.should == [1,2,3,4,5,6]
160
+ new_ary.last.should == 6
161
+ end
162
+
163
+ it "should return only first element if step mentioned is greater that size of the array" do
164
+ ary = [1,2,3,4,5,6]
165
+ new_ary = []
166
+ ary.step_by(10) {|x| new_ary << x}
167
+ new_ary.should == [1]
168
+ end
169
+
170
+ it "should throw ArgumentError if the step mentioned is either zero or negative" do
171
+ lambda{@my_array.step_by(0)}.should raise_error(ArgumentError, "Step can't be 0 or negative")
172
+ lambda{@my_array.step_by(-2)}.should raise_error(ArgumentError, "Step can't be 0 or negative")
173
+ end
174
+
175
+ it "should throw LocalJumpError if no block is provided" do
176
+ lambda{@my_array.step_by(1)}.should raise_error(LocalJumpError, "no block given")
177
+ end
178
+
179
+ end
metadata ADDED
@@ -0,0 +1,62 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: augmented_array
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Niranjan Sarade
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-07-02 00:00:00 +05:30
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: |-
17
+ The Ruby Array class is extended with some traversing methods and you will also be able to get and set the
18
+ individual array elements with indexes as of the indexes were attributes of an array.
19
+ email: nirusuma@gmail.com
20
+ executables: []
21
+
22
+ extensions: []
23
+
24
+ extra_rdoc_files:
25
+ - ./README
26
+ files:
27
+ - lib/augmented_array.rb
28
+ - ./README
29
+ has_rdoc: true
30
+ homepage: http://github.com/NiranjanSarade/augmented_array
31
+ licenses: []
32
+
33
+ post_install_message:
34
+ rdoc_options:
35
+ - --title
36
+ - An Augmented Array
37
+ - --main
38
+ - README
39
+ - --line-numbers
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ version: "0"
47
+ version:
48
+ required_rubygems_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ requirements: []
55
+
56
+ rubyforge_project:
57
+ rubygems_version: 1.3.5
58
+ signing_key:
59
+ specification_version: 3
60
+ summary: An augmented array class with some useful methods
61
+ test_files:
62
+ - spec/augmented_array_spec.rb