signed_multiset 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0c668c57c3959d0bfcb01c8100df51adc41b5608
4
- data.tar.gz: 5058d5b5a8cfa2b2e39bd7e51ab7856617603fcd
3
+ metadata.gz: f89a246862b71b53eeb8ee2f38eadfab7a4b90cf
4
+ data.tar.gz: 30777e6a599eb97385961f21593de03ecd8b0347
5
5
  SHA512:
6
- metadata.gz: 3f7b5820fcab890277e36e6159ce932a2814d7f6da029b94de16a317736b73e5673edd65eb177829cd2b4b7da94e4211cdc3210dc2142c9f39c440152f81eaf9
7
- data.tar.gz: 3610e8eef2ece21ea1ab03a1de1ff2974d8065cad62e0a3449c1f61e22baa366a7d05ce8f1a93e9bbe7ad2e243a1ae339fff8296e8075718aab037f1f7f82b25
6
+ metadata.gz: 000bb39cfbed2233c77e35c9d4062a052648fbc1764fba9a892dc4f3c2327ee36dbafae8650be4f934f3ebc60b32ffd8c0cbf2dff432789aaaeb8e8bff458f81
7
+ data.tar.gz: c9dbf1ca92a7c8dc9905eb119180c7636a61a72e6499176ca95cf7c420bf5d99c3e19130345b341ddaa3f00096ece528699eea76c91fdd267f27a64f771d79ef
data/HISTORY.md CHANGED
@@ -1,3 +1,8 @@
1
+ # 0.2.0
2
+ - Remove the SignedMultiset folder namespace.
3
+ - Replace SignedMultiset[] with SignedMultiset()
4
+ - SignedMultiset() and SignedMultiset.new() both take arrays, hashes, or argument lists as arguments.
5
+
1
6
  # 0.1.0
2
7
  - Fix return values when setting mutliplicity.
3
8
 
data/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
 
8
8
  Signed Multiset is a Ruby implementation of a Multiset that allows negative membership.
9
9
 
10
- You can think of it as a Multiset or Bag that allows for negative counts. It feels like a Ruby Hash or Array, but with some differences:
10
+ You can think of it as a Multiset or Bag that allows for negative counts. It's functionality is very similar to Sorted Sets available in Redis (albeit without the storage functionality). It feels like a Ruby Hash or Array, but with some differences:
11
11
 
12
12
  - A key (any ruby object) can be added to or removed from the SignedMultiset any number of times. The number of times it is included in the multiset (positive or negative) is referred to as it's multiplicity.
13
13
 
@@ -65,7 +65,7 @@ set.cardinality
65
65
  set.size
66
66
  # => 3
67
67
 
68
- other_set = SignedMultiset[:a, :c, :d, :d]
68
+ other_set = SignedMultiset(:a, :c, :d, :d)
69
69
  # => <SignedMultiset a: 1, c: 1, d: 2>
70
70
 
71
71
  set + other_set
@@ -75,7 +75,7 @@ set & other_set
75
75
  # => <SignedMultiset c: 1, d: -3>
76
76
 
77
77
  set | other_set
78
- => <SignedMultiset b: 2, c: 3, d: 2, a: 1>
78
+ # => <SignedMultiset b: 2, c: 3, d: 2, a: 1>
79
79
  ```
80
80
 
81
81
  ## Contributing
@@ -1,2 +1,206 @@
1
- require "signed_multiset/version"
2
- require "signed_multiset/signed_multiset"
1
+ class SignedMultiset
2
+ VERSION = "0.2.0"
3
+
4
+ include Enumerable
5
+ include Comparable
6
+
7
+ # Create a new SignedMultiset instance.
8
+ #
9
+ # @param object [Enumerable, nil] An array of keys, or key-muliplicity pairs.
10
+ def initialize(*args)
11
+ obj = args.count == 1 ? args.first : args
12
+ if obj.respond_to?(:each)
13
+ obj.each { |k, v| increment(k, v || 1) }
14
+ else
15
+ self << obj
16
+ end
17
+ end
18
+
19
+ # Get the non-zero key-multiplicity pairs.
20
+ #
21
+ # @return [Hash]
22
+ def multiplicities
23
+ entries.reject{|k,v| v == 0}
24
+ end
25
+
26
+ # Iterate over the multiplicity collection.
27
+ #
28
+ # @return [Enumerator]
29
+ def each(*args, &block)
30
+ if block_given?
31
+ multiplicities.each { |k,v| yield(k,v) }
32
+ else
33
+ multiplicities.each(args)
34
+ end
35
+ end
36
+
37
+ # Get the multiplicity for a key.
38
+ #
39
+ # @param key [Object] The key to get the multiplicity of
40
+ # @return [Integer, nil] The multiplicity for the key, or nil if the key is
41
+ # not present, or has a zero multiplicity
42
+ def [](key)
43
+ multiplicities[key]
44
+ end
45
+
46
+ # Set the multiplicity for a key.
47
+ #
48
+ # @param key [Object] The key to set the multiplicity of
49
+ # @param multiplicity [Integer] The desired multiplicity
50
+ # @return [Integer] The multiplicity for the key
51
+ def []=(key, multiplicity)
52
+ entries[key] = multiplicity
53
+ self[key]
54
+ end
55
+
56
+ # Increment the multiplicity for a key.
57
+ #
58
+ # @param key (see #[]=)
59
+ # @param value [Integer] The desired increment value, positive or negative
60
+ # @return (see #[]=)
61
+ def increment(key, value)
62
+ entries[key] ||= 0
63
+ entries[key] += value
64
+ self[key]
65
+ end
66
+
67
+ # Increment multiplicity by 1 for a key. This method is chainable.
68
+ #
69
+ # @param key [Object] The key to increment the multiplicity of
70
+ # @return [self]
71
+ def <<(key)
72
+ increment(key, 1)
73
+ self
74
+ end
75
+
76
+ # Remove key completely from the set, similar to [key]=0
77
+ #
78
+ # @param key [Object] The key to remove
79
+ # @return [Integer] The multiplicity of the item removed.
80
+ def delete(key)
81
+ entries.delete(key)
82
+ end
83
+
84
+ # Creates a new instance of equal to current instance
85
+ # @return [SignedMultiset]
86
+ def dup
87
+ self.class.new(multiplicities)
88
+ end
89
+
90
+ # Combine self with another SignedMultiset via addition to create a merged instance.
91
+ #
92
+ # @param other [SignedMultiset]
93
+ # @return [SignedMultiset]
94
+ def +(other)
95
+ other.multiplicities.reduce(self.dup) do |m, (k, v)|
96
+ m.increment(k,v); m
97
+ end
98
+ end
99
+
100
+ # Combine self with another SignedMultiset via subtraction to create a merged instance.
101
+ #
102
+ # @param other (see #+)
103
+ # @return (see #+)
104
+ def -(other)
105
+ other.multiplicities.reduce(self.dup) do |m, (k, v)|
106
+ m.increment(k,-v); m
107
+ end
108
+ end
109
+
110
+ # Combine self with another SignedMultiset via union to create a merged instance.
111
+ #
112
+ # @param other (see #+)
113
+ # @return (see #+)
114
+ def |(other)
115
+ (keys | other.keys).reduce(self.class.new) do |m, k|
116
+ m.increment(k, [self[k] || 0, other[k] || 0].max); m
117
+ end
118
+ end
119
+
120
+ # Combine self with another SignedMultiset via intersection to create a merged instance.
121
+ #
122
+ # @param other (see #+)
123
+ # @return (see #+)
124
+ def &(other)
125
+ (keys & other.keys).reduce(self.class.new) do |m, k|
126
+ m.increment(k, [self[k], other[k]].min); m
127
+ end
128
+ end
129
+
130
+ # Get the list of keys for self.
131
+ #
132
+ # @return [Array]
133
+ def keys
134
+ multiplicities.keys
135
+ end
136
+
137
+ # Get the multiplicity values for self.
138
+ #
139
+ # @return [Array]
140
+ def values
141
+ multiplicities.values
142
+ end
143
+
144
+ # Get the cardinality (sum of multiplicities) for self.
145
+ #
146
+ # @return [Integer]
147
+ def cardinality
148
+ values.inject(&:+)
149
+ end
150
+ alias_method :sum, :cardinality
151
+
152
+ # Get the count of unique keys in the SignedMultiset.
153
+ #
154
+ # @return [Integer]
155
+ def size
156
+ keys.size
157
+ end
158
+ alias_method :length, :size
159
+
160
+ # Compare self with another SignedMultiset
161
+ #
162
+ # @param other (see #+)
163
+ # @return [-1,0,1]
164
+ def <=>(other)
165
+ if [:multiplicities, :cardinality, :size].all? { |m| other.respond_to?(m) }
166
+ if multiplicities == other.multiplicities
167
+ 0
168
+ elsif cardinality != other.cardinality
169
+ cardinality <=> other.cardinality
170
+ elsif size != other.size
171
+ size <=> other.size
172
+ else
173
+ multiplicities <=> other.multiplicities
174
+ end
175
+ end
176
+ end
177
+
178
+ def to_hash
179
+ multiplicities.dup
180
+ end
181
+
182
+ def to_a
183
+ multiplicities.to_a
184
+ end
185
+
186
+ def to_s
187
+ multiplicities.map{ |k,m| "#{k}: #{m}"}.join(', ')
188
+ end
189
+
190
+ def inspect
191
+ "<#{self.class} #{to_s}>"
192
+ end
193
+
194
+ private
195
+
196
+ # Get the key-multiplicity pairs (even those with zero multiplicities).
197
+ #
198
+ # @return [Hash]
199
+ def entries
200
+ @entries ||= {}
201
+ end
202
+ end
203
+
204
+ def SignedMultiset(input)
205
+ SignedMultiset.new(input)
206
+ end
@@ -1,7 +1,7 @@
1
1
  # coding: utf-8
2
2
  lib = File.expand_path('../lib', __FILE__)
3
3
  $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'signed_multiset/version'
4
+ require 'signed_multiset'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "signed_multiset"
@@ -9,17 +9,15 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Josh Lewis"]
10
10
  spec.email = ["josh.w.lewis@gmail.com"]
11
11
  spec.description = %q{Multisets with negative membership}
12
- spec.summary = %q{Signed Multiset is a Ruby implementation of a Multiset that allows negative membership. You can think of it as a Multiset or Bag that allows for negative counts. It feels like a Ruby Hash or Array, but with some differences.}
12
+ spec.summary = %q{You can think of it as a Multiset or Bag that allows for negative counts. It's functionality is very similar to Sorted Sets available in Redis (albeit without the storage functionality). It feels like a Ruby Hash or Array, but with some differences.}
13
13
  spec.homepage = "http://github.com/joshwlewis/signed_multiset"
14
14
  spec.license = "MIT"
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
17
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
- spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.test_files = spec.files.grep(%r{^(test)/})
19
18
  spec.require_paths = ["lib"]
20
19
 
21
20
  spec.add_development_dependency "bundler", "~> 1.3"
22
21
  spec.add_development_dependency "rake"
23
22
  spec.add_development_dependency "minitest"
24
-
25
- end
23
+ end
@@ -1,4 +1,7 @@
1
- require 'test_helper'
1
+ require 'signed_multiset'
2
+ require 'minitest/spec'
3
+ require 'minitest/autorun'
4
+ require 'minitest/pride'
2
5
 
3
6
  describe SignedMultiset do
4
7
  subject { SignedMultiset.new(foo: 4, bar: 2, baz: 0) }
@@ -20,11 +23,8 @@ describe SignedMultiset do
20
23
  set = SignedMultiset.new(subject)
21
24
  set.keys.must_equal([:foo, :bar])
22
25
  end
23
- end
24
-
25
- describe "::[]" do
26
- it "must create a new set" do
27
- set = SignedMultiset[:a, :b, :b, :c]
26
+ it "must accept additional arguments" do
27
+ set = SignedMultiset.new(:a, :b, :c)
28
28
  set.keys.must_equal([:a, :b, :c])
29
29
  end
30
30
  end
@@ -187,8 +187,8 @@ describe SignedMultiset do
187
187
  end
188
188
 
189
189
  describe "#<=>" do
190
- let(:small) { SignedMultiset[:foo, :bar] }
191
- let(:large) { SignedMultiset[:foo, :bar, :baz, :foo, :bar, :qux, :foo, :bar] }
190
+ let(:small) { SignedMultiset.new([:foo, :bar]) }
191
+ let(:large) { SignedMultiset.new([:foo, :bar, :baz, :foo, :bar, :qux, :foo, :bar]) }
192
192
  let(:equal) { subject.dup }
193
193
 
194
194
  it "should return 1 when compared to a smaller set" do
@@ -201,4 +201,11 @@ describe SignedMultiset do
201
201
  (subject <=> equal).must_equal(0)
202
202
  end
203
203
  end
204
+ end
205
+
206
+ describe "::SignedMultiset()" do
207
+ it "must create a new set" do
208
+ set = SignedMultiset([:a, :b, :b, :c])
209
+ set.keys.must_equal([:a, :b, :c])
210
+ end
204
211
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: signed_multiset
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Josh Lewis
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-11 00:00:00.000000000 Z
11
+ date: 2013-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -68,11 +68,8 @@ files:
68
68
  - README.md
69
69
  - Rakefile
70
70
  - lib/signed_multiset.rb
71
- - lib/signed_multiset/signed_multiset.rb
72
- - lib/signed_multiset/version.rb
73
71
  - signed_multiset.gemspec
74
- - test/signed_multiset/signed_multiset_test.rb
75
- - test/test_helper.rb
72
+ - test/signed_multiset_test.rb
76
73
  homepage: http://github.com/joshwlewis/signed_multiset
77
74
  licenses:
78
75
  - MIT
@@ -96,10 +93,9 @@ rubyforge_project:
96
93
  rubygems_version: 2.0.2
97
94
  signing_key:
98
95
  specification_version: 4
99
- summary: Signed Multiset is a Ruby implementation of a Multiset that allows negative
100
- membership. You can think of it as a Multiset or Bag that allows for negative counts.
101
- It feels like a Ruby Hash or Array, but with some differences.
96
+ summary: You can think of it as a Multiset or Bag that allows for negative counts.
97
+ It's functionality is very similar to Sorted Sets available in Redis (albeit without
98
+ the storage functionality). It feels like a Ruby Hash or Array, but with some differences.
102
99
  test_files:
103
- - test/signed_multiset/signed_multiset_test.rb
104
- - test/test_helper.rb
100
+ - test/signed_multiset_test.rb
105
101
  has_rdoc:
@@ -1,206 +0,0 @@
1
- class SignedMultiset
2
-
3
- include Enumerable
4
- include Comparable
5
-
6
- # Create a new instance with a list of objects.
7
- #
8
- # @param *list [Object] A list of objects to add to the set
9
- def self.[](*list)
10
- new(list)
11
- end
12
-
13
- # Create a new SignedMultiset instance.
14
- #
15
- # @param object [Enumerable, nil] An array of keys, or key-muliplicity pairs.
16
- def initialize(object=nil)
17
- if object.is_a?(Enumerable)
18
- object.each { |k, v| increment(k, v || 1) }
19
- end
20
- end
21
-
22
- # Get the non-zero key-multiplicity pairs.
23
- #
24
- # @return [Hash]
25
- def multiplicities
26
- entries.reject{|k,v| v == 0}
27
- end
28
-
29
- # Iterate over the multiplicity collection.
30
- #
31
- # @return [Enumerator]
32
- def each(*args, &block)
33
- if block_given?
34
- multiplicities.each { |k,v| yield(k,v) }
35
- else
36
- multiplicities.each(args)
37
- end
38
- end
39
-
40
- # Get the multiplicity for a key.
41
- #
42
- # @param key [Object] The key to get the multiplicity of
43
- # @return [Integer, nil] The multiplicity for the key, or nil if the key is
44
- # not present, or has a zero multiplicity
45
- def [](key)
46
- multiplicities[key]
47
- end
48
-
49
- # Set the multiplicity for a key.
50
- #
51
- # @param key [Object] The key to set the multiplicity of
52
- # @param multiplicity [Integer] The desired multiplicity
53
- # @return [Integer] The multiplicity for the key
54
- def []=(key, multiplicity)
55
- entries[key] = multiplicity
56
- self[key]
57
- end
58
-
59
- # Increment the multiplicity for a key.
60
- #
61
- # @param key (see #[]=)
62
- # @param value [Integer] The desired increment value, positive or negative
63
- # @return (see #[]=)
64
- def increment(key, value)
65
- entries[key] ||= 0
66
- entries[key] += value
67
- self[key]
68
- end
69
-
70
- # Increment multiplicity by 1 for a key. This method is chainable.
71
- #
72
- # @param key [Object] The key to increment the multiplicity of
73
- # @return [self]
74
- def <<(key)
75
- increment(key, 1)
76
- self
77
- end
78
-
79
- # Remove key completely from the set, similar to [key]=0
80
- #
81
- # @param key [Object] The key to remove
82
- # @return [Integer] The multiplicity of the item removed.
83
- def delete(key)
84
- entries.delete(key)
85
- end
86
-
87
- # Creates a new instance of equal to current instance
88
- # @return [SignedMultiset]
89
- def dup
90
- self.class.new(multiplicities)
91
- end
92
-
93
- # Combine self with another SignedMultiset via addition to create a merged instance.
94
- #
95
- # @param other [SignedMultiset]
96
- # @return [SignedMultiset]
97
- def +(other)
98
- other.multiplicities.reduce(self.dup) do |m, (k, v)|
99
- m.increment(k,v); m
100
- end
101
- end
102
-
103
- # Combine self with another SignedMultiset via subtraction to create a merged instance.
104
- #
105
- # @param other (see #+)
106
- # @return (see #+)
107
- def -(other)
108
- other.multiplicities.reduce(self.dup) do |m, (k, v)|
109
- m.increment(k,-v); m
110
- end
111
- end
112
-
113
- # Combine self with another SignedMultiset via union to create a merged instance.
114
- #
115
- # @param other (see #+)
116
- # @return (see #+)
117
- def |(other)
118
- (keys | other.keys).reduce(self.class.new) do |m, k|
119
- m.increment(k, [self[k] || 0, other[k] || 0].max); m
120
- end
121
- end
122
-
123
- # Combine self with another SignedMultiset via intersection to create a merged instance.
124
- #
125
- # @param other (see #+)
126
- # @return (see #+)
127
- def &(other)
128
- (keys & other.keys).reduce(self.class.new) do |m, k|
129
- m.increment(k, [self[k], other[k]].min); m
130
- end
131
- end
132
-
133
- # Get the list of keys for self.
134
- #
135
- # @return [Array]
136
- def keys
137
- multiplicities.keys
138
- end
139
-
140
- # Get the multiplicity values for self.
141
- #
142
- # @return [Array]
143
- def values
144
- multiplicities.values
145
- end
146
-
147
- # Get the cardinality (sum of multiplicities) for self.
148
- #
149
- # @return [Integer]
150
- def cardinality
151
- values.inject(&:+)
152
- end
153
- alias_method :sum, :cardinality
154
-
155
- # Get the count of unique keys in the SignedMultiset.
156
- #
157
- # @return [Integer]
158
- def size
159
- keys.size
160
- end
161
- alias_method :length, :size
162
-
163
- # Compare self with another SignedMultiset
164
- #
165
- # @param other (see #+)
166
- # @return [-1,0,1]
167
- def <=>(other)
168
- if [:multiplicities, :cardinality, :size].all? { |m| other.respond_to?(m) }
169
- if multiplicities == other.multiplicities
170
- 0
171
- elsif cardinality != other.cardinality
172
- cardinality <=> other.cardinality
173
- elsif size != other.size
174
- size <=> other.size
175
- else
176
- multiplicities <=> other.multiplicities
177
- end
178
- end
179
- end
180
-
181
- def to_hash
182
- multiplicities.dup
183
- end
184
-
185
- def to_a
186
- multiplicities.to_a
187
- end
188
-
189
- def to_s
190
- multiplicities.map{ |k,m| "#{k}: #{m}"}.join(', ')
191
- end
192
-
193
- def inspect
194
- "<#{self.class} #{to_s}>"
195
- end
196
-
197
- private
198
-
199
- # Get the key-multiplicity pairs (even those with zero multiplicities).
200
- #
201
- # @return [Hash]
202
- def entries
203
- @entries ||= {}
204
- end
205
-
206
- end
@@ -1,3 +0,0 @@
1
- class SignedMultiset
2
- VERSION = "0.1.0"
3
- end
data/test/test_helper.rb DELETED
@@ -1,4 +0,0 @@
1
- require 'signed_multiset'
2
- require 'minitest/spec'
3
- require 'minitest/autorun'
4
- require 'minitest/pride'