ruby-tables 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1 @@
1
+ *.swp
@@ -0,0 +1,56 @@
1
+ = Description
2
+ This library provides a ruby implementation of a Table data structure from lua.
3
+
4
+ Tables are essentially a combination of hashes and arrays.
5
+
6
+ They're more for convenience than anything else, but they provide setters and getters
7
+ for symbolized keys in hashes and uniform hash and array like access.
8
+
9
+ Any methods from the Enumerable module should work and will treat the table as an array,
10
+ ignoring any pairs inside it.
11
+
12
+ = Caveats
13
+ As in lua, hash keys cannot be numeric indices. If you intend to use numeric hash keys,
14
+ they should be inside an array, such as:
15
+ Table[ [ 2 ] => 4 ]
16
+
17
+ Unlike in lua, where an error is raised if you attempt to use numerical keys, ruby-tables
18
+ will change all numerical keys into [ index ] as shown above.
19
+
20
+ That is:
21
+ t = Table[ 1, 2, 3, { 4 => 5 } ]
22
+ t[ 4 ] = 5
23
+ t.pairs #=> { [ 4 ] => 5 }
24
+ t.to_a #=> [ 1, 2, 3, nil, 5 ]
25
+ t[ [ 4 ] ] = 50
26
+ t.pairs #=> { [ 4 ] => 50 }
27
+
28
+ Notice above that index 3 was set to a nil value. That's because numeric indexes are filled
29
+ in when you create a key well out of bounds. This is not unlike typical ruby Arrays:
30
+ ary = [ 1 ]
31
+ ary[ 10 ] = 2
32
+ ary #=> [ 1, nil, nil, nil, nil, nil, nil, nil, nil, nil, 2 ]
33
+
34
+ = Examples
35
+ # as hashes with convient dot notation for keys
36
+ t1 = Table[ :something => 50, :else => 100 ]
37
+ t1.something #=> 50
38
+ t1.something = 100
39
+ t1.something #=> 100
40
+ t1.some_new_key = "sdsdsd"
41
+ t1.some_new_key #=> "sdsdsd"
42
+
43
+ # as a combination of an array and a hash
44
+ t2 = Table[ 1, 2, 3, 4, 5, { :a => 1000, :b => 2000 }, 6, 7, { :c => 50, :d => 60 }, 8, 9 ]
45
+
46
+ # the size method returns the number of array values inside the table, this is identical
47
+ # to lua's length operator (#table)
48
+ t2.size #=> 9
49
+
50
+ t2.each_pair { | k, v | print k } #=> abcd
51
+
52
+ # tables can be concatenated
53
+ t3 = t1 + t2
54
+ t3.pairs #=> { :something => 50, :else => 100, :a => 1000, :b => 2000, :c => 50, :d => 60 }
55
+ t3.to_a #=> [ 1, 2, 3, 4, 5, 6, 7, 8, 9 ]
56
+ t3.inject { |sum, i | sum + i } #=> 45
@@ -0,0 +1,32 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.version = "0.1.0"
8
+ gem.name = "ruby-tables"
9
+ gem.summary = %Q{Ruby implementation of lua tables}
10
+ gem.description = %Q{A table data structure implemented in ruby}
11
+ gem.email = "nick.loves.rails@gmail.com"
12
+ gem.homepage = "http://github.com/Abica/ruby-tables"
13
+ gem.authors = [ "Nicholas Wright" ]
14
+ gem.add_development_dependency "rspec", ">= 1.2.2"
15
+ gem.has_rdoc = true
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
+ end
21
+
22
+ task :default => :spec
23
+
24
+ require 'rake/rdoctask'
25
+ Rake::RDocTask.new do |rdoc|
26
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
27
+
28
+ rdoc.rdoc_dir = 'rdoc'
29
+ rdoc.title = "ruby-tables #{version}"
30
+ rdoc.rdoc_files.include('README*')
31
+ rdoc.rdoc_files.include('lib/**/*.rb')
32
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.1
@@ -0,0 +1,193 @@
1
+ # Implements a table data structure
2
+ class Table
3
+ include Enumerable
4
+
5
+ # takes a comma separated list of arrays and hashes and returns a table
6
+ #
7
+ # example:
8
+ # Table[ 1, 2, 3, 4, { :a => 3, :b => 5 }, 7, 8, { :c => 33 } ]
9
+ def self.[] *args
10
+ new *args
11
+ end
12
+
13
+ def initialize *args
14
+ @values = []
15
+ @records = {}
16
+ process *args
17
+ end
18
+
19
+ # returns the value corresponding to the index or key
20
+ #
21
+ # t = Table[ 1, 2, "string", { :a => 4, :b => 5 }, 3, 4 ]
22
+ # t[ 2 ] #=> "string"
23
+ # t[ :a ] #=> 4
24
+ #
25
+ # symbolized keys are also accessible via dot notation:
26
+ #
27
+ # t.a #=> 4
28
+ # t.b #=> 5
29
+ def [] key
30
+ if key.is_a? Integer
31
+ @values[ key ]
32
+ else
33
+ @records[ key ]
34
+ end
35
+ end
36
+
37
+ # updates the value for a given key or index
38
+ # if no entry exists for the given key or index then one is created
39
+ #
40
+ # t = Table[ :a => "abcde", :b => 44332211 ]
41
+ # t[ :a ] = 43
42
+ # t[ :a ] #=> 43
43
+ # t[ 0 ] = 54
44
+ # t.first #=> 54
45
+ #
46
+ # note that like an array, if you insert a value into a table at an
47
+ # index that doesn't yet exist, any gaps will be filled in with nil
48
+ # such as:
49
+ #
50
+ # t[ 5 ] = 100
51
+ # t.to_a #=> [ 54, nil, nil, nil, 100 ]
52
+ #
53
+ # symbolized keys also have setters so that you can use dot notation:
54
+ #
55
+ # t.a = "bbcec"
56
+ # t.a #=> "bbcec"
57
+ def []= key, value
58
+ if key.is_a? Integer
59
+ @values[ key ] = value
60
+ else
61
+ process_hash key => value
62
+ end
63
+ end
64
+
65
+ # add a hash or value to this table
66
+ #
67
+ # t = Table[ 1, 2, 3 ]
68
+ # t << { :a => 4, :b => 4 }
69
+ def << arg
70
+ process arg
71
+ end
72
+
73
+ # combines 2 tables
74
+ #
75
+ # Table[ :a => 4, :b => 5 ] + Table[ 1, 2, 3, 4, { :c => 4 } ]
76
+ def + other
77
+ values = self.to_a + other.to_a
78
+ Table[ self.pairs, other.pairs, *values ]
79
+ end
80
+
81
+ # returns the first non pair item in the table
82
+ #
83
+ # t = Table[ { :a => 4 }, 1, 2, 3, 4, { :b => 4, :c => 23 } ]
84
+ # t.first #=> 1
85
+ def first
86
+ @values.first
87
+ end
88
+
89
+ # returns the last non pair item in the table
90
+ #
91
+ # t = Table[ { :a => 4 }, 1, 2, 3, 4, { :b => 4, :c => 23 } ]
92
+ # t.last #=> 4
93
+ def last
94
+ @values.last
95
+ end
96
+
97
+ # returns the length of all integer indexes
98
+ #
99
+ # t = Table[ 1, 2, { :b => 4 }, 3, 4 ]
100
+ # t.size #=> 4
101
+ def size
102
+ @values.size
103
+ end
104
+
105
+ alias length size
106
+
107
+ # iterate through each of the array values
108
+ def each &block
109
+ @values.each &block
110
+ end
111
+
112
+ # sort the array values
113
+ #
114
+ # t = Table[ 2, 23, 54, { :a => 4 }, 49 ]
115
+ # t.sort #=> [ 2, 23, 49, 54 ]
116
+ def sort &block
117
+ @values.sort &block
118
+ end
119
+
120
+ # iterate through the key => value pairs in the table
121
+ def each_pair &block
122
+ @records.each_pair &block
123
+ end
124
+
125
+ # iterate through the hash keys in the table
126
+ def each_key &block
127
+ @records.each_key &block
128
+ end
129
+
130
+ # returns a hash of all key => value pairs inside the table
131
+ #
132
+ # t = Table[ 1, { :a => 4 }, 2, { :b => 543 } ]
133
+ # t.pairs #=> { :a => 4, :b => 543 }
134
+ def pairs
135
+ @records
136
+ end
137
+
138
+ # return an array of all hash keys in the table
139
+ #
140
+ # t = Table[ 1, 2, { :a => 55, :b => 77 }, 3, { :c => 22 } ]
141
+ # t.keys #=> [ :a, :b, :c ]
142
+ def keys
143
+ @records.keys
144
+ end
145
+
146
+ # returns an array of all hash values in the table
147
+ #
148
+ # t = Table[ 1, 2, { :a => 55, :b => 77 }, 3, { :c => 22 } ]
149
+ # t.values #=> [ 55, 77, 22 ]
150
+ def values
151
+ @records.values
152
+ end
153
+
154
+ private
155
+ def process *args
156
+ args.each do | arg |
157
+ if arg.is_a? Hash
158
+ process_hash arg
159
+ else
160
+ @values << arg
161
+ end
162
+ end
163
+ end
164
+
165
+ def process_hash hsh
166
+ hsh.each do | key, value |
167
+ key = [ key ] if key.is_a? Integer
168
+ @records[ key ] = value
169
+
170
+ next unless key.is_a? Symbol
171
+ next if respond_to? key and respond_to? "#{ key }="
172
+
173
+ instance_eval <<-EOM
174
+ def #{ key }
175
+ @records[ :#{ key } ]
176
+ end
177
+
178
+ def #{ key }= value
179
+ @records[ :#{ key } ] = value
180
+ end
181
+ EOM
182
+ end
183
+ end
184
+
185
+ # if an accessor is called that doesn't exist, the key => value
186
+ # are added into the table
187
+ def method_missing meth_id, *args
188
+ name = meth_id.id2name
189
+ if key = name[ /(\w+)=/, 1 ]
190
+ process_hash key.to_sym => args.first
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,51 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{ruby-tables}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Nicholas Wright"]
12
+ s.date = %q{2010-02-13}
13
+ s.description = %q{A table data structure implemented in ruby}
14
+ s.email = %q{nick.loves.rails@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README.rdoc"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "README.rdoc",
21
+ "Rakefile",
22
+ "VERSION",
23
+ "lib/table.rb",
24
+ "ruby-tables.gemspec",
25
+ "spec/spec_helper.rb",
26
+ "spec/table_spec.rb"
27
+ ]
28
+ s.homepage = %q{http://github.com/Abica/ruby-tables}
29
+ s.rdoc_options = ["--charset=UTF-8"]
30
+ s.require_paths = ["lib"]
31
+ s.rubygems_version = %q{1.3.5}
32
+ s.summary = %q{Ruby implementation of lua tables}
33
+ s.test_files = [
34
+ "spec/spec_helper.rb",
35
+ "spec/table_spec.rb"
36
+ ]
37
+
38
+ if s.respond_to? :specification_version then
39
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
40
+ s.specification_version = 3
41
+
42
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
43
+ s.add_development_dependency(%q<rspec>, [">= 1.2.2"])
44
+ else
45
+ s.add_dependency(%q<rspec>, [">= 1.2.2"])
46
+ end
47
+ else
48
+ s.add_dependency(%q<rspec>, [">= 1.2.2"])
49
+ end
50
+ end
51
+
@@ -0,0 +1,4 @@
1
+ require File.join( File.dirname( __FILE__ ), "..", "lib", "table" )
2
+
3
+ Spec::Runner.configure do | config |
4
+ end
@@ -0,0 +1,193 @@
1
+ require File.join( "spec", "spec_helper" )
2
+
3
+ describe Table do
4
+ before :all do
5
+ @args = [ 1, 2, 3, 4, 5, { :k => 4 }, 7, 8, { :v => 10 } ]
6
+ @array_vals = @args.reject { | a | a.is_a? Hash }
7
+ @table = Table[ *@args ]
8
+ end
9
+
10
+ describe "[]" do
11
+ it "is a new Table instance" do
12
+ t = Table[ *@args ]
13
+
14
+ t.should be_a( Table )
15
+ end
16
+ end
17
+
18
+ describe "#self.[]" do
19
+ it "returns the value at index" do
20
+ @array_vals.each_with_index do | val, i |
21
+ @table[ i ].should == val
22
+ end
23
+ end
24
+
25
+ it "returns the value at key" do
26
+ @table[ :k ].should == @args[ 5 ][ :k ]
27
+ @table[ :v ].should == @args[ 8 ][ :v ]
28
+ end
29
+ end
30
+
31
+ describe "#[]=" do
32
+ it "creates a new value at index" do
33
+ i = 500
34
+ new_value = "something_new"
35
+ @table[ i ].should be_nil
36
+ @table[ i ] = new_value
37
+ @table[ i ].should == new_value
38
+ @table.size.should >= i
39
+ end
40
+
41
+ it "updates the value at index" do
42
+ i = 3
43
+ old_value = @args[ i ]
44
+ new_value = 34903489034
45
+ @table[ i ].should == old_value
46
+ @table[ i ] = new_value
47
+ @table[ i ].should == new_value
48
+ end
49
+
50
+ it "creates a new value for key" do
51
+ key = :something_long_and_fake
52
+ new_value = 0b0110
53
+ @table[ key ].should be_nil
54
+ @table[ key ] = new_value
55
+ @table[ key ].should == new_value
56
+ end
57
+
58
+ it "updates the value for key" do
59
+ key = :v
60
+ old_value = @args[ 8 ][ key ]
61
+ new_value = 50000000
62
+
63
+ @table[ key ].should == old_value
64
+ @table[ key ] = new_value
65
+
66
+ @table[ key ].should == new_value
67
+ end
68
+ end
69
+
70
+ describe "#<<" do
71
+ it "pushes an argument onto the table" do
72
+ vals = [ 4000, [ 5, 0, 0, 0 ], "6000" ]
73
+ vals.each do | val |
74
+ @table << val
75
+ @table.last.should == val
76
+ end
77
+
78
+ hsh = { :this => 1, :was => 2, :added => 3 }
79
+ @table << hsh
80
+ hsh.each do | k, v |
81
+ @table[ k ].should == v
82
+ end
83
+ end
84
+ end
85
+
86
+ describe "#+" do
87
+ before :all do
88
+ @t1 = Table[ 1, 2, 3, { :a => 5, :b => 6 } ]
89
+ @t2 = Table[ 4, 5, { :c => 7, :d => 8 }, 6 ]
90
+ @t3 = @t1 + @t2
91
+ end
92
+
93
+ it "should combine 2 tables together" do
94
+ @t3.to_a.should == [ 1, 2, 3, 4, 5, 6 ]
95
+ pairs = @t3.pairs
96
+ [ :a, :b, :c, :d ].each do | key |
97
+ pairs.should have_key( key )
98
+ end
99
+ end
100
+ end
101
+
102
+ describe "#first" do
103
+ it "should return the first array element" do
104
+ t = Table[ *50..80 ]
105
+ t.first.should == 50
106
+
107
+ t = Table[ :a => 4, :b => 5, :c => 6 ]
108
+ t.first.should be_nil
109
+ end
110
+ end
111
+
112
+ describe "#last" do
113
+ it "should return the last array element" do
114
+ t = Table[ *50..80 ]
115
+ t.last.should == 80
116
+
117
+ t = Table[ :a => 4, :b => 5, :c => 6 ]
118
+ t.last.should be_nil
119
+
120
+ t = Table[ 1, 2, 3, { :a => 4, :b => 5, :c => 6 }, 600, 700, 800 ]
121
+ t.last.should == 800
122
+ end
123
+ end
124
+
125
+ describe "#size" do
126
+ it "should return the number of array elements in the table" do
127
+ @table.size.should == @array_vals.size
128
+ end
129
+
130
+ it "should be the same as length" do
131
+ @table.size.should == @table.length
132
+ end
133
+ end
134
+
135
+ describe "#sort" do
136
+ it "returns a sorted array" do
137
+ rand_vals = @array_vals.sort_by { rand }
138
+ sorted_vals = rand_vals.sort
139
+
140
+ t = Table[ *rand_vals ]
141
+ t.to_a.should_not == sorted_vals
142
+ t.sort.should == sorted_vals
143
+ end
144
+ end
145
+
146
+ describe "#pairs" do
147
+ it "returns a hash of all of the key => value pairs" do
148
+ pairs = @table.pairs
149
+ [ :k, :v ].each do | key |
150
+ pairs.should have_key( key )
151
+ end
152
+ end
153
+ end
154
+
155
+ describe "#keys" do
156
+ it "returns an array of all hash keys" do
157
+ pairs = @table.pairs
158
+ [ :k, :v ].each do | key |
159
+ pairs.should have_key( key )
160
+ end
161
+ end
162
+ end
163
+
164
+ describe "#values" do
165
+ it "returns an array of all hash values" do
166
+ @table.values.sort.should == [ 4, 10 ]
167
+ end
168
+ end
169
+
170
+ describe "setters for hash keys" do
171
+ it "should add a key if one doesn't exist" do
172
+ key = :super_long_key_name
173
+ meth_name = "#{ key }="
174
+ value = 349348908340
175
+ @table.should_not respond_to( meth_name )
176
+ @table.send meth_name, value
177
+ @table.should respond_to( meth_name )
178
+ @table[ key ].should == value
179
+ end
180
+
181
+ it "should override an existing key" do
182
+ @table.v.should == 10
183
+ @table.v = 50
184
+ @table.v.should == 50
185
+ end
186
+ end
187
+
188
+ describe "getters for hash keys" do
189
+ it "returns the value for a key" do
190
+ @table.v.should == 10
191
+ end
192
+ end
193
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-tables
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Nicholas Wright
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-13 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.2.2
24
+ version:
25
+ description: A table data structure implemented in ruby
26
+ email: nick.loves.rails@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - README.rdoc
33
+ files:
34
+ - .gitignore
35
+ - README.rdoc
36
+ - Rakefile
37
+ - VERSION
38
+ - lib/table.rb
39
+ - ruby-tables.gemspec
40
+ - spec/spec_helper.rb
41
+ - spec/table_spec.rb
42
+ has_rdoc: true
43
+ homepage: http://github.com/Abica/ruby-tables
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options:
48
+ - --charset=UTF-8
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ version: "0"
56
+ version:
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: "0"
62
+ version:
63
+ requirements: []
64
+
65
+ rubyforge_project:
66
+ rubygems_version: 1.3.5
67
+ signing_key:
68
+ specification_version: 3
69
+ summary: Ruby implementation of lua tables
70
+ test_files:
71
+ - spec/spec_helper.rb
72
+ - spec/table_spec.rb