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]]
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!
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 |