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
72 73 74 |
# File 'lib/multimap.rb', line 72 def initialize(default = []) super end |
Class Method Details
.[](*args) ⇒ Object
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]]
439 440 441 442 443 |
# File 'lib/multimap.rb', line 439 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]
119 120 121 122 123 124 125 |
# File 'lib/multimap.rb', line 119 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
141 142 143 144 145 |
# File 'lib/multimap.rb', line 141 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]
160 161 162 |
# File 'lib/multimap.rb', line 160 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]
182 183 184 185 186 |
# File 'lib/multimap.rb', line 182 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
202 203 204 205 206 |
# File 'lib/multimap.rb', line 202 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
222 223 224 225 226 227 228 |
# File 'lib/multimap.rb', line 222 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
244 245 246 247 248 |
# File 'lib/multimap.rb', line 244 def each_value each_pair do |_, value| yield value end end |
#freeze ⇒ Object
:nodoc:
250 251 252 253 254 |
# File 'lib/multimap.rb', line 250 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
266 267 268 |
# File 'lib/multimap.rb', line 266 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
281 282 283 |
# File 'lib/multimap.rb', line 281 def index(value) invert[value] end |
#initialize_copy(original) ⇒ Object
:nodoc:
76 77 78 79 80 81 |
# File 'lib/multimap.rb', line 76 def initialize_copy(original) #:nodoc: super clear original.each_pair { |key, container| self[key] = container } self.default = original.default.dup 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"]
315 316 317 318 319 |
# File 'lib/multimap.rb', line 315 def invert h = self.class.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"])
329 330 331 332 333 |
# File 'lib/multimap.rb', line 329 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]
360 361 362 |
# File 'lib/multimap.rb', line 360 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]
294 295 296 297 298 299 300 301 302 303 304 305 |
# File 'lib/multimap.rb', line 294 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]
397 398 399 400 401 402 |
# File 'lib/multimap.rb', line 397 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
345 346 347 |
# File 'lib/multimap.rb', line 345 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]}
100 101 102 103 104 105 |
# File 'lib/multimap.rb', line 100 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]]
412 413 414 415 416 417 418 |
# File 'lib/multimap.rb', line 412 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] }
427 428 429 |
# File 'lib/multimap.rb', line 427 def to_hash dup end |
#update(other) ⇒ Object Also known as: merge!
375 376 377 378 379 380 381 382 383 384 385 |
# File 'lib/multimap.rb', line 375 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]
453 454 455 456 457 |
# File 'lib/multimap.rb', line 453 def values values = [] each_value { |value| values << value } values end |