Class: Multimap
- Inherits:
-
Object
- Object
- Multimap
- Extended by:
- Forwardable
- Includes:
- Enumerable
- Defined in:
- lib/rack/mount/vendor/multimap/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.
Example
require 'multimap'
map = Multimap.new
map["a"] = 100
map["b"] = 200
map["a"] = 300
map["a"] # -> [100, 300]
map["b"] # -> [200]
map.keys # -> #<Multiset: {a, a, b}>
Direct Known Subclasses
Class Method Summary collapse
-
.[](*args) ⇒ Object
call-seq: Multimap[ [key =>|, value]* ] => multimap.
Instance Method Summary collapse
-
#==(other) ⇒ Object
:nodoc:.
-
#[](key) ⇒ Object
Retrieves the value object corresponding to the *keys object.
-
#containers ⇒ Object
call-seq: map.containers => array.
-
#delete(key, value = nil) ⇒ Object
call-seq: map.delete(key, value) => value map.delete(key) => value.
-
#delete_if ⇒ Object
call-seq: map.delete_if {| key, value | block } -> map.
-
#each ⇒ Object
call-seq: map.each { |key, value| block } => map.
-
#each_association(&block) ⇒ 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.
-
#eql?(other) ⇒ Boolean
:nodoc:.
-
#freeze ⇒ Object
:nodoc:.
-
#has_value?(value) ⇒ Boolean
(also: #value?)
call-seq: map.has_value?(value) => true or false map.value?(value) => true or false.
-
#include?(key) ⇒ Boolean
(also: #member?)
Returns true if the given key is present in Multimap.
-
#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.
-
#marshal_dump ⇒ Object
:nodoc:.
-
#marshal_load(hash) ⇒ Object
:nodoc:.
-
#merge(other) ⇒ Object
call-seq: map.merge(other_map) => multimap.
-
#reject(&block) ⇒ Object
call-seq: map.reject {| key, value | block } -> map.
-
#reject!(&block) ⇒ Object
call-seq: map.reject! {| key, value | block } -> map or nil.
-
#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.
-
#to_yaml(opts = {}) ⇒ Object
:nodoc:.
-
#update(other) ⇒ Object
(also: #merge!)
call-seq: map.merge!(other_map) => multimap map.update(other_map) => multimap.
-
#values ⇒ Object
call-seq: map.values => array.
-
#values_at(*keys) ⇒ Object
Return an array containing the values associated with the given keys.
-
#yaml_initialize(tag, val) ⇒ Object
:nodoc:.
Constructor Details
#initialize(default = []) ⇒ Multimap
75 76 77 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 75 def initialize(default = []) @hash = Hash.new(default) end |
Class Method Details
.[](*args) ⇒ Object
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 60 61 62 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 30 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 = new map.instance_variable_set(:@hash, Hash[*args]) map.default = default map end |
Instance Method Details
#==(other) ⇒ Object
:nodoc:
252 253 254 255 256 257 258 259 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 252 def ==(other) #:nodoc: case other when Multimap @hash == other._internal_hash else @hash == other end end |
#[](key) ⇒ Object
Retrieves the value object corresponding to the *keys object.
91 92 93 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 91 def [](key) @hash[key] end |
#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]]
507 508 509 510 511 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 507 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]
126 127 128 129 130 131 132 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 126 def delete(key, value = nil) if value @hash[key].delete(value) else @hash.delete(key) end end |
#delete_if ⇒ Object
call-seq:
map.delete_if {| key, value | block } -> map
Deletes every key-value pair from map for which block evaluates to true
.
map = Multimap["a" => 100, "b" => [200, 300]]
map.delete_if {|key, value| value >= 300 }
#=> Multimap["a" => 100, "b" => 200]
315 316 317 318 319 320 321 322 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 315 def delete_if each_association do |key, container| container.delete_if do |value| yield [key, value] end end self 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
148 149 150 151 152 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 148 def each each_pair do |key, value| yield [key, value] end end |
#each_association(&block) ⇒ 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]
167 168 169 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 167 def each_association(&block) @hash.each_pair(&block) 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]
184 185 186 187 188 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 184 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
204 205 206 207 208 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 204 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
224 225 226 227 228 229 230 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 224 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
246 247 248 249 250 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 246 def each_value each_pair do |_, value| yield value end end |
#eql?(other) ⇒ Boolean
:nodoc:
261 262 263 264 265 266 267 268 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 261 def eql?(other) #:nodoc: case other when Multimap @hash.eql?(other._internal_hash) else @hash.eql?(other) end end |
#freeze ⇒ Object
:nodoc:
270 271 272 273 274 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 270 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
286 287 288 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 286 def has_value?(value) values.include?(value) end |
#include?(key) ⇒ Boolean Also known as: member?
Returns true if the given key is present in Multimap.
398 399 400 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 398 def include?(key) keys.include?(key) 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
301 302 303 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 301 def index(value) invert[value] end |
#initialize_copy(original) ⇒ Object
:nodoc:
79 80 81 82 83 84 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 79 def initialize_copy(original) #:nodoc: @hash = Hash.new(original.default.dup) original._internal_hash.each_pair do |key, container| @hash[key] = container.dup end 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"]
377 378 379 380 381 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 377 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"])
391 392 393 394 395 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 391 def keys keys = Multiset.new each_key { |key| keys << key } keys end |
#marshal_dump ⇒ Object
:nodoc:
532 533 534 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 532 def marshal_dump #:nodoc: @hash end |
#marshal_load(hash) ⇒ Object
:nodoc:
536 537 538 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 536 def marshal_load(hash) #:nodoc: @hash = hash 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]
428 429 430 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 428 def merge(other) dup.update(other) end |
#reject(&block) ⇒ Object
call-seq:
map.reject {| key, value | block } -> map
Same as Multimap#delete_if
, but works on (and returns) a copy of the map. Equivalent to map.dup.delete_if
.
331 332 333 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 331 def reject(&block) dup.delete_if(&block) end |
#reject!(&block) ⇒ Object
call-seq:
map.reject! {| key, value | block } -> map or nil
Equivalent to Multimap#delete_if
, but returns nil
if no changes were made.
341 342 343 344 345 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 341 def reject!(&block) old_size = size delete_if(&block) old_size == size ? nil : self 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]
356 357 358 359 360 361 362 363 364 365 366 367 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 356 def replace(other) case other when Array @hash.replace(self.class[self.default, *other]) when Hash @hash.replace(self.class[self.default, other]) when self.class @hash.replace(other) 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]
465 466 467 468 469 470 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 465 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
413 414 415 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 413 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]}
107 108 109 110 111 112 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 107 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]]
480 481 482 483 484 485 486 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 480 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] }
495 496 497 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 495 def to_hash @hash.dup end |
#to_yaml(opts = {}) ⇒ Object
:nodoc:
540 541 542 543 544 545 546 547 548 549 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 540 def to_yaml(opts = {}) #:nodoc: YAML::quick_emit(self, opts) do |out| out.map(taguri, to_yaml_style) do |map| @hash.each do |k, v| map.add(k, v) end map.add('__default__', @hash.default) end end end |
#update(other) ⇒ Object Also known as: merge!
443 444 445 446 447 448 449 450 451 452 453 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 443 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]
521 522 523 524 525 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 521 def values values = [] each_value { |value| values << value } values end |
#values_at(*keys) ⇒ Object
Return an array containing the values associated with the given keys.
528 529 530 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 528 def values_at(*keys) @hash.values_at(*keys) end |
#yaml_initialize(tag, val) ⇒ Object
:nodoc:
551 552 553 554 555 556 |
# File 'lib/rack/mount/vendor/multimap/multimap.rb', line 551 def yaml_initialize(tag, val) #:nodoc: default = val.delete('__default__') @hash = val @hash.default = default self end |