PageRenderTime 62ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/External.LCA_RESTRICTED/Languages/Ruby/ruby-1.8.6p368/lib/ruby/gems/1.8/gems/rack-mount-0.3.2/lib/rack/mount/vendor/multimap/multimap.rb

https://github.com/kevinsheffield/ironruby
Ruby | 532 lines | 222 code | 41 blank | 269 comment | 16 complexity | fdec4b1a8441a6b15b854d6ff891a31d MD5 | raw file
Possible License(s): CC-BY-SA-3.0, LGPL-2.1, MIT, GPL-2.0
  1. require 'forwardable'
  2. require 'multiset'
  3. # Multimap is a generalization of a map or associative array
  4. # abstract data type in which more than one value may be associated
  5. # with and returned for a given key.
  6. class Multimap
  7. extend Forwardable
  8. include Enumerable
  9. # call-seq:
  10. # Multimap[ [key =>|, value]* ] => multimap
  11. #
  12. # Creates a new multimap populated with the given objects.
  13. #
  14. # Multimap["a", 100, "b", 200] #=> {"a"=>[100], "b"=>[200]}
  15. # Multimap["a" => 100, "b" => 200] #=> {"a"=>[100], "b"=>[200]}
  16. def self.[](*args)
  17. default = []
  18. if args.size == 2 && args.last.is_a?(Hash)
  19. default = args.shift
  20. elsif !args.first.is_a?(Hash) && args.size % 2 == 1
  21. default = args.shift
  22. end
  23. if args.size == 1 && args.first.is_a?(Hash)
  24. args[0] = args.first.inject({}) { |hash, (key, value)|
  25. unless value.is_a?(default.class)
  26. value = (default.dup << value)
  27. end
  28. hash[key] = value
  29. hash
  30. }
  31. else
  32. index = 0
  33. args.map! { |value|
  34. unless index % 2 == 0 || value.is_a?(default.class)
  35. value = (default.dup << value)
  36. end
  37. index += 1
  38. value
  39. }
  40. end
  41. map = new
  42. map.instance_variable_set(:@hash, Hash[*args])
  43. map.default = default
  44. map
  45. end
  46. # call-seq:
  47. # Multimap.new => multimap
  48. # Multimap.new(default) => multimap
  49. #
  50. # Returns a new, empty multimap.
  51. #
  52. # map = Multimap.new(Set.new)
  53. # h["a"] = 100
  54. # h["b"] = 200
  55. # h["a"] #=> [100].to_set
  56. # h["c"] #=> [].to_set
  57. def initialize(default = [])
  58. @hash = Hash.new(default)
  59. end
  60. def initialize_copy(original) #:nodoc:
  61. @hash = Hash.new(original.default.dup)
  62. original._internal_hash.each_pair do |key, container|
  63. @hash[key] = container.dup
  64. end
  65. end
  66. def_delegators :@hash, :clear, :default, :default=, :empty?,
  67. :fetch, :has_key?, :key?
  68. # Retrieves the <i>value</i> object corresponding to the
  69. # <i>*keys</i> object.
  70. def [](key)
  71. @hash[key]
  72. end
  73. # call-seq:
  74. # map[key] = value => value
  75. # map.store(key, value) => value
  76. #
  77. # Associates the value given by <i>value</i> with the key
  78. # given by <i>key</i>. Unlike a regular hash, multiple can be
  79. # assoicated with the same value.
  80. #
  81. # map = Multimap["a" => 100, "b" => 200]
  82. # map["a"] = 9
  83. # map["c"] = 4
  84. # map #=> {"a" => [100, 9], "b" => [200], "c" => [4]}
  85. def store(key, value)
  86. update_container(key) do |container|
  87. container << value
  88. container
  89. end
  90. end
  91. alias_method :[]=, :store
  92. # call-seq:
  93. # map.delete(key, value) => value
  94. # map.delete(key) => value
  95. #
  96. # Deletes and returns a key-value pair from <i>map</i>. If only
  97. # <i>key</i> is given, all the values matching that key will be
  98. # deleted.
  99. #
  100. # map = Multimap["a" => 100, "b" => [200, 300]]
  101. # map.delete("b", 300) #=> 300
  102. # map.delete("a") #=> [100]
  103. def delete(key, value = nil)
  104. if value
  105. @hash[key].delete(value)
  106. else
  107. @hash.delete(key)
  108. end
  109. end
  110. # call-seq:
  111. # map.each { |key, value| block } => map
  112. #
  113. # Calls <i>block</i> for each key/value pair in <i>map</i>, passing
  114. # the key and value to the block as a two-element array.
  115. #
  116. # map = Multimap["a" => 100, "b" => [200, 300]]
  117. # map.each { |key, value| puts "#{key} is #{value}" }
  118. #
  119. # <em>produces:</em>
  120. #
  121. # a is 100
  122. # b is 200
  123. # b is 300
  124. def each
  125. each_pair do |key, value|
  126. yield [key, value]
  127. end
  128. end
  129. # call-seq:
  130. # map.each_association { |key, container| block } => map
  131. #
  132. # Calls <i>block</i> once for each key/container in <i>map</i>, passing
  133. # the key and container to the block as parameters.
  134. #
  135. # map = Multimap["a" => 100, "b" => [200, 300]]
  136. # map.each_association { |key, container| puts "#{key} is #{container}" }
  137. #
  138. # <em>produces:</em>
  139. #
  140. # a is [100]
  141. # b is [200, 300]
  142. def each_association(&block)
  143. @hash.each_pair(&block)
  144. end
  145. # call-seq:
  146. # map.each_container { |container| block } => map
  147. #
  148. # Calls <i>block</i> for each container in <i>map</i>, passing the
  149. # container as a parameter.
  150. #
  151. # map = Multimap["a" => 100, "b" => [200, 300]]
  152. # map.each_container { |container| puts container }
  153. #
  154. # <em>produces:</em>
  155. #
  156. # [100]
  157. # [200, 300]
  158. def each_container
  159. each_association do |_, container|
  160. yield container
  161. end
  162. end
  163. # call-seq:
  164. # map.each_key { |key| block } => map
  165. #
  166. # Calls <i>block</i> for each key in <i>hsh</i>, passing the key
  167. # as a parameter.
  168. #
  169. # map = Multimap["a" => 100, "b" => [200, 300]]
  170. # map.each_key { |key| puts key }
  171. #
  172. # <em>produces:</em>
  173. #
  174. # a
  175. # b
  176. # b
  177. def each_key
  178. each_pair do |key, _|
  179. yield key
  180. end
  181. end
  182. # call-seq:
  183. # map.each_pair { |key_value_array| block } => map
  184. #
  185. # Calls <i>block</i> for each key/value pair in <i>map</i>,
  186. # passing the key and value as parameters.
  187. #
  188. # map = Multimap["a" => 100, "b" => [200, 300]]
  189. # map.each_pair { |key, value| puts "#{key} is #{value}" }
  190. #
  191. # <em>produces:</em>
  192. #
  193. # a is 100
  194. # b is 200
  195. # b is 300
  196. def each_pair
  197. each_association do |key, values|
  198. values.each do |value|
  199. yield key, value
  200. end
  201. end
  202. end
  203. # call-seq:
  204. # map.each_value { |value| block } => map
  205. #
  206. # Calls <i>block</i> for each key in <i>map</i>, passing the
  207. # value as a parameter.
  208. #
  209. # map = Multimap["a" => 100, "b" => [200, 300]]
  210. # map.each_value { |value| puts value }
  211. #
  212. # <em>produces:</em>
  213. #
  214. # 100
  215. # 200
  216. # 300
  217. def each_value
  218. each_pair do |_, value|
  219. yield value
  220. end
  221. end
  222. def ==(other) #:nodoc:
  223. case other
  224. when Multimap
  225. @hash == other._internal_hash
  226. else
  227. @hash == other
  228. end
  229. end
  230. def eql?(other) #:nodoc:
  231. case other
  232. when Multimap
  233. @hash.eql?(other._internal_hash)
  234. else
  235. @hash.eql?(other)
  236. end
  237. end
  238. def freeze #:nodoc:
  239. each_container { |container| container.freeze }
  240. default.freeze
  241. super
  242. end
  243. # call-seq:
  244. # map.has_value?(value) => true or false
  245. # map.value?(value) => true or false
  246. #
  247. # Returns <tt>true</tt> if the given value is present for any key
  248. # in <i>map</i>.
  249. #
  250. # map = Multimap["a" => 100, "b" => [200, 300]]
  251. # map.has_value?(300) #=> true
  252. # map.has_value?(999) #=> false
  253. def has_value?(value)
  254. values.include?(value)
  255. end
  256. alias_method :value?, :has_value?
  257. # call-seq:
  258. # map.index(value) => key
  259. #
  260. # Returns the key for a given value. If not found, returns
  261. # <tt>nil</tt>.
  262. #
  263. # map = Multimap["a" => 100, "b" => [200, 300]]
  264. # map.index(100) #=> "a"
  265. # map.index(200) #=> "b"
  266. # map.index(999) #=> nil
  267. def index(value)
  268. invert[value]
  269. end
  270. # call-seq:
  271. # map.delete_if {| key, value | block } -> map
  272. #
  273. # Deletes every key-value pair from <i>map</i> for which <i>block</i>
  274. # evaluates to <code>true</code>.
  275. #
  276. # map = Multimap["a" => 100, "b" => [200, 300]]
  277. # map.delete_if {|key, value| value >= 300 }
  278. # #=> Multimap["a" => 100, "b" => 200]
  279. #
  280. def delete_if
  281. each_association do |key, container|
  282. container.delete_if do |value|
  283. yield [key, value]
  284. end
  285. end
  286. self
  287. end
  288. # call-seq:
  289. # map.reject {| key, value | block } -> map
  290. #
  291. # Same as <code>Multimap#delete_if</code>, but works on (and returns) a
  292. # copy of the <i>map</i>. Equivalent to
  293. # <code><i>map</i>.dup.delete_if</code>.
  294. #
  295. def reject(&block)
  296. dup.delete_if(&block)
  297. end
  298. # call-seq:
  299. # map.reject! {| key, value | block } -> map or nil
  300. #
  301. # Equivalent to <code>Multimap#delete_if</code>, but returns
  302. # <code>nil</code> if no changes were made.
  303. #
  304. def reject!(&block)
  305. old_size = size
  306. delete_if(&block)
  307. old_size == size ? nil : self
  308. end
  309. # call-seq:
  310. # map.replace(other_map) => map
  311. #
  312. # Replaces the contents of <i>map</i> with the contents of
  313. # <i>other_map</i>.
  314. #
  315. # map = Multimap["a" => 100, "b" => 200]
  316. # map.replace({ "c" => 300, "d" => 400 })
  317. # #=> Multimap["c" => 300, "d" => 400]
  318. def replace(other)
  319. case other
  320. when Array
  321. @hash.replace(self.class[self.default, *other])
  322. when Hash
  323. @hash.replace(self.class[self.default, other])
  324. when self.class
  325. @hash.replace(other)
  326. else
  327. raise ArgumentError
  328. end
  329. end
  330. # call-seq:
  331. # map.invert => multimap
  332. #
  333. # Returns a new multimap created by using <i>map</i>'s values as keys,
  334. # and the keys as values.
  335. #
  336. # map = Multimap["n" => 100, "m" => 100, "d" => [200, 300]]
  337. # map.invert #=> Multimap[100 => ["n", "m"], 200 => "d", 300 => "d"]
  338. def invert
  339. h = self.class.new(default.dup)
  340. each_pair { |key, value| h[value] = key }
  341. h
  342. end
  343. # call-seq:
  344. # map.keys => multiset
  345. #
  346. # Returns a new +Multiset+ populated with the keys from this hash. See also
  347. # <tt>Multimap#values</tt> and <tt>Multimap#containers</tt>.
  348. #
  349. # map = Multimap["a" => 100, "b" => [200, 300], "c" => 400]
  350. # map.keys #=> Multiset.new(["a", "b", "b", "c"])
  351. def keys
  352. keys = Multiset.new
  353. each_key { |key| keys << key }
  354. keys
  355. end
  356. # Returns true if the given key is present in Multimap.
  357. def include?(key)
  358. keys.include?(key)
  359. end
  360. alias_method :member?, :include?
  361. # call-seq:
  362. # map.length => fixnum
  363. # map.size => fixnum
  364. #
  365. # Returns the number of key-value pairs in the map.
  366. #
  367. # map = Multimap["a" => 100, "b" => [200, 300], "c" => 400]
  368. # map.length #=> 4
  369. # map.delete("a") #=> 100
  370. # map.length #=> 3
  371. def size
  372. values.size
  373. end
  374. alias_method :length, :size
  375. # call-seq:
  376. # map.merge(other_map) => multimap
  377. #
  378. # Returns a new multimap containing the contents of <i>other_map</i> and
  379. # the contents of <i>map</i>.
  380. #
  381. # map1 = Multimap["a" => 100, "b" => 200]
  382. # map2 = Multimap["a" => 254, "c" => 300]
  383. # map2.merge(map2) #=> Multimap["a" => 100, "b" => [200, 254], "c" => 300]
  384. # map1 #=> Multimap["a" => 100, "b" => 200]
  385. def merge(other)
  386. dup.update(other)
  387. end
  388. # call-seq:
  389. # map.merge!(other_map) => multimap
  390. # map.update(other_map) => multimap
  391. #
  392. # Adds each pair from <i>other_map</i> to <i>map</i>.
  393. #
  394. # map1 = Multimap["a" => 100, "b" => 200]
  395. # map2 = Multimap["b" => 254, "c" => 300]
  396. #
  397. # map1.merge!(map2)
  398. # #=> Multimap["a" => 100, "b" => [200, 254], "c" => 300]
  399. def update(other)
  400. case other
  401. when self.class
  402. other.each_pair { |key, value| store(key, value) }
  403. when Hash
  404. update(self.class[self.default, other])
  405. else
  406. raise ArgumentError
  407. end
  408. self
  409. end
  410. alias_method :merge!, :update
  411. # call-seq:
  412. # map.select { |key, value| block } => multimap
  413. #
  414. # Returns a new Multimap consisting of the pairs for which the
  415. # block returns true.
  416. #
  417. # map = Multimap["a" => 100, "b" => 200, "c" => 300]
  418. # map.select { |k,v| k > "a" } #=> Multimap["b" => 200, "c" => 300]
  419. # map.select { |k,v| v < 200 } #=> Multimap["a" => 100]
  420. def select
  421. inject(self.class.new) { |map, (key, value)|
  422. map[key] = value if yield([key, value])
  423. map
  424. }
  425. end
  426. # call-seq:
  427. # map.to_a => array
  428. #
  429. # Converts <i>map</i> to a nested array of [<i>key,
  430. # value</i>] arrays.
  431. #
  432. # map = Multimap["a" => 100, "b" => [200, 300], "c" => 400]
  433. # map.to_a #=> [["a", 100], ["b", 200], ["b", 300], ["c", 400]]
  434. def to_a
  435. ary = []
  436. each_pair do |key, value|
  437. ary << [key, value]
  438. end
  439. ary
  440. end
  441. # call-seq:
  442. # map.to_hash => hash
  443. #
  444. # Converts <i>map</i> to a basic hash.
  445. #
  446. # map = Multimap["a" => 100, "b" => [200, 300]]
  447. # map.to_hash #=> { "a" => [100], "b" => [200, 300] }
  448. def to_hash
  449. @hash.dup
  450. end
  451. # call-seq:
  452. # map.containers => array
  453. #
  454. # Returns a new array populated with the containers from <i>map</i>. See
  455. # also <tt>Multimap#keys</tt> and <tt>Multimap#values</tt>.
  456. #
  457. # map = Multimap["a" => 100, "b" => [200, 300]]
  458. # map.containers #=> [[100], [200, 300]]
  459. def containers
  460. containers = []
  461. each_container { |container| containers << container }
  462. containers
  463. end
  464. # call-seq:
  465. # map.values => array
  466. #
  467. # Returns a new array populated with the values from <i>map</i>. See
  468. # also <tt>Multimap#keys</tt> and <tt>Multimap#containers</tt>.
  469. #
  470. # map = Multimap["a" => 100, "b" => [200, 300]]
  471. # map.values #=> [100, 200, 300]
  472. def values
  473. values = []
  474. each_value { |value| values << value }
  475. values
  476. end
  477. # Return an array containing the values associated with the given keys.
  478. def values_at(*keys)
  479. @hash.values_at(*keys)
  480. end
  481. protected
  482. def _internal_hash #:nodoc:
  483. @hash
  484. end
  485. def update_container(key) #:nodoc:
  486. container = @hash[key]
  487. container = container.dup if container.equal?(default)
  488. container = yield(container)
  489. @hash[key] = container
  490. end
  491. end