Class: Multimap
- Inherits:
-
Hash
- Object
- Hash
- Multimap
- Defined in:
- lib/multimap.rb
Overview
Multimap is a generalization of a map or associative array abstract data type in which more than one value may be associated with and returned for a given key.
Direct Known Subclasses
Class Method Summary collapse
-
.[](*args) ⇒ Object
call-seq: Multimap[ [key =>|, value]* ] => multimap.
Instance Method Summary collapse
-
#containers ⇒ Object
call-seq: map.containers => array.
-
#delete(key, value = nil) ⇒ Object
call-seq: map.delete(key, value) => value map.delete(key) => value.
-
#each ⇒ Object
call-seq: map.each { |key, value| block } => map.
-
#each_association ⇒ Object
call-seq: map.each_association { |key, container| block } => map.
-
#each_container ⇒ Object
call-seq: map.each_container { |container| block } => map.
-
#each_key ⇒ Object
call-seq: map.each_key { |key| block } => map.
-
#each_pair ⇒ Object
call-seq: map.each_pair { |key_value_array| block } => map.
-
#each_value ⇒ Object
call-seq: map.each_value { |value| block } => map.
-
#freeze ⇒ Object
:nodoc:.
-
#has_value?(value) ⇒ Boolean
(also: #value?)
call-seq: map.has_value?(value) => true or false map.value?(value) => true or false.
-
#index(value) ⇒ Object
call-seq: map.index(value) => key.
-
#initialize(default = []) ⇒ Multimap
constructor
call-seq: Multimap.new => multimap Multimap.new(default) => multimap.
-
#initialize_copy(original) ⇒ Object
:nodoc:.
-
#invert ⇒ Object
call-seq: map.invert => multimap.
-
#keys ⇒ Object
call-seq: map.keys => multiset.
-
#merge(other) ⇒ Object
call-seq: map.merge(other_map) => multimap.
-
#replace(other) ⇒ Object
call-seq: map.replace(other_map) => map.
-
#select ⇒ Object
call-seq: map.select { |key, value| block } => multimap.
-
#size ⇒ Object
(also: #length)
call-seq: map.length => fixnum map.size => fixnum.
-
#store(key, value) ⇒ Object
(also: #[]=)
call-seq: map = value => value map.store(key, value) => value.
-
#to_a ⇒ Object
call-seq: map.to_a => array.
-
#to_hash ⇒ Object
call-seq: map.to_hash => hash.
-
#update(other) ⇒ Object
(also: #merge!)
call-seq: map.merge!(other_map) => multimap map.update(other_map) => multimap.
-
#values ⇒ Object
call-seq: map.values => array.
Constructor Details
#initialize(default = []) ⇒ Multimap
call-seq:
Multimap.new => multimap
Multimap.new(default) => multimap
Returns a new, empty multimap.
map = Multimap.new(Set.new)
h["a"] = 100
h["b"] = 200
h["a"] #=> [100].to_set
h["c"] #=> [].to_set
72 73 74 |
# File 'lib/multimap.rb', line 72 def initialize(default = []) super end |
Class Method Details
.[](*args) ⇒ Object
call-seq:
Multimap[ [key =>|, value]* ] => multimap
Creates a new multimap populated with the given objects.
Multimap["a", 100, "b", 200] #=> {"a"=>[100], "b"=>[200]}
Multimap["a" => 100, "b" => 200] #=> {"a"=>[100], "b"=>[200]}
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'lib/multimap.rb', line 28 def self.[](*args) default = [] if args.size == 2 && args.last.is_a?(Hash) default = args.shift elsif !args.first.is_a?(Hash) && args.size % 2 == 1 default = args.shift end if args.size == 1 && args.first.is_a?(Hash) args[0] = args.first.inject({}) { |hash, (key, value)| unless value.is_a?(default.class) value = (default.dup << value) end hash[key] = value hash } else index = 0 args.map! { |value| unless index % 2 == 0 || value.is_a?(default.class) value = (default.dup << value) end index += 1 value } end map = super map.default = default map end |
Instance Method Details
#containers ⇒ Object
call-seq:
map.containers => array
Returns a new array populated with the containers from map. See also Multimap#keys and Multimap#values.
map = Multimap["a" => 100, "b" => [200, 300]]
map.containers #=> [[100], [200, 300]]
433 434 435 436 437 |
# File 'lib/multimap.rb', line 433 def containers containers = [] each_container { |container| containers << container } containers end |
#delete(key, value = nil) ⇒ Object
call-seq:
map.delete(key, value) => value
map.delete(key) => value
Deletes and returns a key-value pair from map. If only key is given, all the values matching that key will be deleted.
map = Multimap["a" => 100, "b" => [200, 300]]
map.delete("b", 300) #=> 300
map.delete("a") #=> [100]
113 114 115 116 117 118 119 |
# File 'lib/multimap.rb', line 113 def delete(key, value = nil) if value hash_aref(key).delete(value) else super(key) end end |
#each ⇒ Object
call-seq:
map.each { |key, value| block } => map
Calls block for each key/value pair in map, passing the key and value to the block as a two-element array.
map = Multimap["a" => 100, "b" => [200, 300]]
map.each { |key, value| puts "#{key} is #{value}" }
produces:
a is 100
b is 200
b is 300
135 136 137 138 139 |
# File 'lib/multimap.rb', line 135 def each each_pair do |key, value| yield [key, value] end end |
#each_association ⇒ Object
call-seq:
map.each_association { |key, container| block } => map
Calls block once for each key/container in map, passing the key and container to the block as parameters.
map = Multimap["a" => 100, "b" => [200, 300]]
map.each_association { |key, container| puts "#{key} is #{container}" }
produces:
a is [100]
b is [200, 300]
154 155 156 |
# File 'lib/multimap.rb', line 154 def each_association # each_pair end |
#each_container ⇒ Object
call-seq:
map.each_container { |container| block } => map
Calls block for each container in map, passing the container as a parameter.
map = Multimap["a" => 100, "b" => [200, 300]]
map.each_container { |container| puts container }
produces:
[100]
[200, 300]
176 177 178 179 180 |
# File 'lib/multimap.rb', line 176 def each_container each_association do |_, container| yield container end end |
#each_key ⇒ Object
call-seq:
map.each_key { |key| block } => map
Calls block for each key in hsh, passing the key as a parameter.
map = Multimap["a" => 100, "b" => [200, 300]]
map.each_key { |key| puts key }
produces:
a
b
b
196 197 198 199 200 |
# File 'lib/multimap.rb', line 196 def each_key each_pair do |key, _| yield key end end |
#each_pair ⇒ Object
call-seq:
map.each_pair { |key_value_array| block } => map
Calls block for each key/value pair in map, passing the key and value as parameters.
map = Multimap["a" => 100, "b" => [200, 300]]
map.each_pair { |key, value| puts "#{key} is #{value}" }
produces:
a is 100
b is 200
b is 300
216 217 218 219 220 221 222 |
# File 'lib/multimap.rb', line 216 def each_pair each_association do |key, values| values.each do |value| yield key, value end end end |
#each_value ⇒ Object
call-seq:
map.each_value { |value| block } => map
Calls block for each key in map, passing the value as a parameter.
map = Multimap["a" => 100, "b" => [200, 300]]
map.each_value { |value| puts value }
produces:
100
200
300
238 239 240 241 242 |
# File 'lib/multimap.rb', line 238 def each_value each_pair do |_, value| yield value end end |
#freeze ⇒ Object
:nodoc:
244 245 246 247 248 |
# File 'lib/multimap.rb', line 244 def freeze #:nodoc: each_container { |container| container.freeze } default.freeze super end |
#has_value?(value) ⇒ Boolean Also known as: value?
call-seq:
map.has_value?(value) => true or false
map.value?(value) => true or false
Returns true if the given value is present for any key in map.
map = Multimap["a" => 100, "b" => [200, 300]]
map.has_value?(300) #=> true
map.has_value?(999) #=> false
260 261 262 |
# File 'lib/multimap.rb', line 260 def has_value?(value) values.include?(value) end |
#index(value) ⇒ Object
call-seq:
map.index(value) => key
Returns the key for a given value. If not found, returns nil.
map = Multimap["a" => 100, "b" => [200, 300]]
map.index(100) #=> "a"
map.index(200) #=> "b"
map.index(999) #=> nil
275 276 277 |
# File 'lib/multimap.rb', line 275 def index(value) invert[value] end |
#initialize_copy(original) ⇒ Object
:nodoc:
76 77 78 79 80 |
# File 'lib/multimap.rb', line 76 def initialize_copy(original) #:nodoc: super clear original.each_pair { |key, container| self[key] = container } end |
#invert ⇒ Object
call-seq:
map.invert => multimap
Returns a new multimap created by using map’s values as keys, and the keys as values.
map = Multimap["n" => 100, "m" => 100, "d" => [200, 300]]
map.invert #=> Multimap[100 => ["n", "m"], 200 => "d", 300 => "d"]
309 310 311 312 313 |
# File 'lib/multimap.rb', line 309 def invert h = Multimap.new(default.dup) each_pair { |key, value| h[value] = key } h end |
#keys ⇒ Object
call-seq:
map.keys => multiset
Returns a new Multiset populated with the keys from this hash. See also Multimap#values and Multimap#containers.
map = Multimap["a" => 100, "b" => [200, 300], "c" => 400]
map.keys #=> Multiset.new(["a", "b", "b", "c"])
323 324 325 326 327 |
# File 'lib/multimap.rb', line 323 def keys keys = Multiset.new each_key { |key| keys << key } keys end |
#merge(other) ⇒ Object
call-seq:
map.merge(other_map) => multimap
Returns a new multimap containing the contents of other_map and the contents of map.
map1 = Multimap["a" => 100, "b" => 200]
map2 = Multimap["a" => 254, "c" => 300]
map2.merge(map2) #=> Multimap["a" => 100, "b" => [200, 254], "c" => 300]
map1 #=> Multimap["a" => 100, "b" => 200]
354 355 356 |
# File 'lib/multimap.rb', line 354 def merge(other) dup.update(other) end |
#replace(other) ⇒ Object
call-seq:
map.replace(other_map) => map
Replaces the contents of map with the contents of other_map.
map = Multimap["a" => 100, "b" => 200]
map.replace({ "c" => 300, "d" => 400 })
#=> Multimap["c" => 300, "d" => 400]
288 289 290 291 292 293 294 295 296 297 298 299 |
# File 'lib/multimap.rb', line 288 def replace(other) case other when Array super(self.class[self.default, *other]) when Hash super(self.class[self.default, other]) when self.class super else raise ArgumentError end end |
#select ⇒ Object
call-seq:
map.select { |key, value| block } => multimap
Returns a new Multimap consisting of the pairs for which the block returns true.
map = Multimap["a" => 100, "b" => 200, "c" => 300]
map.select { |k,v| k > "a" } #=> Multimap["b" => 200, "c" => 300]
map.select { |k,v| v < 200 } #=> Multimap["a" => 100]
391 392 393 394 395 396 |
# File 'lib/multimap.rb', line 391 def select inject(self.class.new) { |map, (key, value)| map[key] = value if yield([key, value]) map } end |
#size ⇒ Object Also known as: length
call-seq:
map.length => fixnum
map.size => fixnum
Returns the number of key-value pairs in the map.
map = Multimap["a" => 100, "b" => [200, 300], "c" => 400]
map.length #=> 4
map.delete("a") #=> 100
map.length #=> 3
339 340 341 |
# File 'lib/multimap.rb', line 339 def size values.size end |
#store(key, value) ⇒ Object Also known as: []=
call-seq:
map[key] = value => value
map.store(key, value) => value
Associates the value given by value with the key given by key. Unlike a regular hash, multiple can be assoicated with the same value.
map = Multimap["a" => 100, "b" => 200]
map["a"] = 9
map["c"] = 4
map #=> {"a" => [100, 9], "b" => [200], "c" => [4]}
94 95 96 97 98 99 |
# File 'lib/multimap.rb', line 94 def store(key, value) update_container(key) do |container| container << value container end end |
#to_a ⇒ Object
call-seq:
map.to_a => array
Converts map to a nested array of [key, value] arrays.
map = Multimap["a" => 100, "b" => [200, 300], "c" => 400]
map.to_a #=> [["a", 100], ["b", 200], ["b", 300], ["c", 400]]
406 407 408 409 410 411 412 |
# File 'lib/multimap.rb', line 406 def to_a ary = [] each_pair do |key, value| ary << [key, value] end ary end |
#to_hash ⇒ Object
call-seq:
map.to_hash => hash
Converts map to a basic hash.
map = Multimap["a" => 100, "b" => [200, 300]]
map.to_hash #=> { "a" => [100], "b" => [200, 300] }
421 422 423 |
# File 'lib/multimap.rb', line 421 def to_hash dup end |
#update(other) ⇒ Object Also known as: merge!
call-seq:
map.merge!(other_map) => multimap
map.update(other_map) => multimap
Adds each pair from other_map to map.
map1 = Multimap["a" => 100, "b" => 200]
map2 = Multimap["b" => 254, "c" => 300]
map1.merge!(map2)
#=> Multimap["a" => 100, "b" => [200, 254], "c" => 300]
369 370 371 372 373 374 375 376 377 378 379 |
# File 'lib/multimap.rb', line 369 def update(other) case other when self.class other.each_pair { |key, value| store(key, value) } when Hash update(self.class[self.default, other]) else raise ArgumentError end self end |
#values ⇒ Object
call-seq:
map.values => array
Returns a new array populated with the values from map. See also Multimap#keys and Multimap#containers.
map = Multimap["a" => 100, "b" => [200, 300]]
map.values #=> [100, 200, 300]
447 448 449 450 451 |
# File 'lib/multimap.rb', line 447 def values values = [] each_value { |value| values << value } values end |