augmented_array 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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