multiset 0.3.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,23 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'autotest/restart'
4
+
5
+ # Autotest.add_hook :initialize do |at|
6
+ # at.extra_files << "../some/external/dependency.rb"
7
+ #
8
+ # at.libs << ":../some/external"
9
+ #
10
+ # at.add_exception 'vendor'
11
+ #
12
+ # at.add_mapping(/dependency.rb/) do |f, _|
13
+ # at.files_matching(/test_.*rb$/)
14
+ # end
15
+ #
16
+ # %w(TestA TestB).each do |klass|
17
+ # at.extra_class_map[klass] = "test/test_misc.rb"
18
+ # end
19
+ # end
20
+
21
+ # Autotest.add_hook :run_command do |at|
22
+ # system "rake build"
23
+ # end
File without changes
@@ -0,0 +1,206 @@
1
+ === 0.1.0 / 2008-02-09
2
+
3
+ (ja)
4
+ * 公開開始。
5
+
6
+ (en)
7
+ * First distribution.
8
+
9
+ === 0.1.1 / 2008-02-12
10
+
11
+ (ja)
12
+ * Multiset#&の実装が誤っていたのを修正。
13
+ * ドキュメントの間違いを修正。
14
+
15
+ (en)
16
+ * Fixed: Wrong implementation of Multiset#&
17
+ * Fixed: Wrong documentation
18
+
19
+ === 0.1.2 / 2008-02-16
20
+
21
+ (ja)
22
+ * Hash#to_multisetに冗長な処理があったので修正。
23
+ * Multisetにメソッドmap, map!, collect, collect!, map_with, map_with!を追加。
24
+ * これに伴い、従来のMultiset#mapなどとは挙動が変更されました。
25
+ (従来のMultiset#mapなどはEnumerable#mapを呼んでいたので、
26
+ 返り値は配列でした。)
27
+
28
+ (en)
29
+ * Fixed: Removing redundant process in Hash#to_multiset
30
+ * Added: Methods: map, map!, collect, collect!, map_with, map_with! on Multiset
31
+ * As a result, what Multiset#map and other methods do has changed.
32
+ (As of version 0.11, Multiset#map returns an array, because
33
+ Multiset#map means Enumerable#map.)
34
+
35
+ === 0.1.3 / 2008-03-01
36
+
37
+ (ja)
38
+ * setup.rb(http://i.loveruby.net/ja/projects/setup/)を用いたインストールに対応した。
39
+
40
+ (en)
41
+ * Made setup.rb(http://i.loveruby.net/en/projects/setup/) be avaliable.
42
+
43
+ === 0.1.3.1 / 2008-03-02
44
+
45
+ (ja)
46
+ * ドキュメントの間違いを修正。
47
+
48
+ (en)
49
+ * Fixed: Wrong documentation
50
+
51
+ === 0.2.0 / 2008-03-23
52
+
53
+ (ja)
54
+ * Multimapクラスを追加。またこれに伴い、Hash#to_multimap・Hash#multimap
55
+ メソッドを追加。
56
+ * Multiset.parse、Multiset.parse_force、Multiset.parse_string、
57
+ Multiset.parse_string?メソッドを追加。
58
+ * Multiset#==において、引数がMultisetのインスタンスでない場合、
59
+ 強制的にfalseを返すようにした。
60
+ * Multiset#subset?、Multiset#superset?、Multiset#proper_subset?、
61
+ Multiset#proper_superset?において、引数がMultisetのインスタンスで
62
+ ない場合、強制的にArgumentErrorを発生するようにした。
63
+
64
+ (en)
65
+ * Added: Multimap class, Hash#to_multimap, Hash#multimap
66
+ * Added: Multiset.parse, Multiset.parse_force, Multiset.parse_string, Multiset.parse_string?
67
+ * Changed: In Multiset#==, if the argument is not an instance of Multiset,
68
+ Multiset#== always returns false.
69
+ * Changed: In Multiset#subset?, Multiset#superset?, Multiset#proper_subset?
70
+ and Multiset#proper_superset?, if the argument is not an instance of Multiset,
71
+ those methods always raise ArgumentError.
72
+
73
+ === 0.2.0.1 / 2008-03-25
74
+
75
+ (ja)
76
+ * Multiset#classify、Multiset#classify_withの返り値をMultimapにした。
77
+ * Multimap#to_s、Multimap#inspectを追加。(ドキュメントは省略させていただきます)
78
+ * Multiset#to_sの実装が誤っていたのを修正。
79
+
80
+ (en)
81
+ * Changed: Multiset#classify, Multiset#classify_with returns a Multimap.
82
+ * Added: Multimap#to_s, Multimap#inspect (No document)
83
+ * Fixed: Wrong implementation of Multiset#to_s
84
+
85
+ === 0.2.0.2 / 2008-04-23
86
+
87
+ (ja)
88
+ * (setup.rbの)GNU LGPLの文書を添付していなかったので追加
89
+
90
+ (en)
91
+ * Added the text of GNU LGPL to the archive (for setup.rb)
92
+
93
+ === 0.3.0 / 2011-3-24
94
+
95
+ (ja)
96
+ * Rubygemsでの公開を開始。
97
+
98
+ (en)
99
+ * Released for Rubygems
100
+
101
+ === 0.4.0 / 2012-08-16
102
+
103
+ (ja)
104
+ * テストケースを追加。
105
+ * Multiset.parse_string、Multiset.parse_string?メソッドを削除。
106
+ * Ruby1.9でString#eachが削除されたため。
107
+ 文字列を行単位で区切ってMultisetにしたい場合は、Multiset.parse_forceを
108
+ ご利用下さい。
109
+ * Multiset.from_linesメソッドを新設。(文字列のみ渡せます。挙動はMultiset.parse_forceと同じです)
110
+ * Multiset#countはEnumerable#countと同様、ブロックを与えることが可能になりました。
111
+ * Multiset#each, Multiset#each_item, Multiset#each_pairは、ブロックを与えなかった場合にEnumeratorを返すようになりました。
112
+ * 以下のエイリアスを追加。(主に、Enumerableのメソッド名に合わせるため)
113
+ * Multiset#sample (Multiset#randに同じ)
114
+ * Multiset#group_by (Multiset#classifyに同じ)
115
+ * Multiset#group_by_with (Multiset#classify_withに同じ)
116
+ * Multiset#each_with_count (Multiset#each_pairに同じ)
117
+ * 以下の「含まれている要素とその個数について繰り返す」メソッドを追加。
118
+ * Multiset#find_with, Multiset#detect_with
119
+ * Multiset#find_all_with, Multiset#select_with
120
+ * Multiset#reject_with
121
+ * Multiset#inject_with, Multiset#reduce_with
122
+ * Multiset#max_with
123
+ * Multiset#min_with
124
+ * Multiset#minmax_with
125
+ * Multiset#max_by_with
126
+ * Multiset#min_by_with
127
+ * Multiset#minmax_by_with
128
+ * Multiset#sort_with
129
+ * Multiset#sort_by_with
130
+ * バージョン0.4.0より、以下のメソッドはArrayではなくMultisetを返します。
131
+ * Multiset#map, Multiset#collect
132
+ * Multiset#map!, Multiset#collect!
133
+ * Multiset#find_all, Multiset#select
134
+ * Multiset#grep
135
+ * Multiset#reject
136
+ * バージョン0.4.0より、以下のメソッドはHashではなくMultimapを返します。
137
+ * Multiset#group_by (returned as a result of becoming an alias of Multiset#classify)
138
+ * バージョン0.4.0より、以下のメソッドは冗長な処理を回避する仕様となっています。具体的には、これまではMultiset#eachに従って同じ要素を何度もブロックに渡していたものを、Multiset#each_itemに従って同じ要素は1度しかブロックに渡さなくなりました。例えば、Multiset[:a, :a, :a, :b].map{ ... }は新しい挙動ではブロックを2回しか呼びません(これまでの挙動では4回呼んでいた)。
139
+ * Multiset#map, Multiset#collect
140
+ * Multiset#map!, Multiset#collect!
141
+ * Multiset#find_all, Multiset#select
142
+ * Multiset#grep
143
+ * Multiset#reject
144
+ * Multiset#reject!
145
+ * Multiset#delete_if
146
+ * Multiset#classify
147
+ * Multiset#max
148
+ * Multiset#min
149
+ * Multiset#minmax
150
+ * Multiset#max_by
151
+ * Multiset#min_by
152
+ * Multiset#minmax_by
153
+ * Multiset#sort
154
+ * Multiset#sort_by
155
+
156
+ (en)
157
+ * Added: Test codes
158
+ * Removed: Multiset.parse_string, Multiset.parse_string?
159
+ * Because Ruby 1.9 does not support String#each
160
+ * Multiset.parse_force is still available.
161
+ * Added: Multiset.from_lines (equivalent to Multiset.parse_force, but only a string is accepted)
162
+ * Fixed: Multiset#count behaves like Enumerable#count: you can give it a block.
163
+ * Fixed: Multiset#each, Multiset#each_item, Multiset#each_pair: they return an Enumerator if no block is given.
164
+ * Added: Some aliases (mainly to fit with the methods in Enumerable)
165
+ * Multiset#sample (alias of Multiset#rand)
166
+ * Multiset#group_by (alias of Multiset#classify)
167
+ * Multiset#group_by_with (alias of Multiset#classify_with)
168
+ * Multiset#each_with_count (alias of Multiset#each_pair)
169
+ * Added: Iteration methods which gives pairs of items/counts
170
+ * Multiset#find_with, Multiset#detect_with
171
+ * Multiset#find_all_with, Multiset#select_with
172
+ * Multiset#reject_with
173
+ * Multiset#inject_with, Multiset#reduce_with
174
+ * Multiset#max_with
175
+ * Multiset#min_with
176
+ * Multiset#minmax_with
177
+ * Multiset#max_by_with
178
+ * Multiset#min_by_with
179
+ * Multiset#minmax_by_with
180
+ * Multiset#sort_with
181
+ * Multiset#sort_by_with
182
+ * Modified: The following methods are to return a Multiset rather than an Array since version 0.4.0.
183
+ * Multiset#map, Multiset#collect
184
+ * Multiset#map!, Multiset#collect!
185
+ * Multiset#find_all, Multiset#select
186
+ * Multiset#grep
187
+ * Multiset#reject
188
+ * Modified: The following methods are to return a Multimap rather than a Hash of Arrays since version 0.4.0.
189
+ * Multiset#group_by (returned as a result of becoming an alias of Multiset#classify)
190
+ * Modified: To avoid redundancy, following methods are to scan the Multiset for each (non-duplicated) elements since 0.4.0, that is, the same behavior as Multiset#each_item. For example, Multiset[:a, :a, :a, :b].map{ ... } calls the block for only twice, which is 4 times in the old behavior.
191
+ * Multiset#map, Multiset#collect
192
+ * Multiset#map!, Multiset#collect!
193
+ * Multiset#find_all, Multiset#select
194
+ * Multiset#grep
195
+ * Multiset#reject
196
+ * Multiset#reject!
197
+ * Multiset#delete_if
198
+ * Multiset#classify
199
+ * Multiset#max
200
+ * Multiset#min
201
+ * Multiset#minmax
202
+ * Multiset#max_by
203
+ * Multiset#min_by
204
+ * Multiset#minmax_by
205
+ * Multiset#sort
206
+ * Multiset#sort_by
@@ -0,0 +1,84 @@
1
+ = multiset
2
+
3
+ * http://maraigue.hhiro.net/multiset/
4
+
5
+ Ruby implementation of the multiset
6
+
7
+ == DESCRIPTION:
8
+
9
+ Unlike ordinary set(see Ruby documentation for "set" library), multiset can contain two or more same items.
10
+
11
+ Set[:a,:b,:c,:b,:b,:c] # => #<Set: {:b, :c, :a}>
12
+ Multiset[:a,:b,:c,:b,:b,:c] # => #<Multiset:#3 :b, #2 :c, #1 :a>
13
+
14
+ Multisets are typically used for counting elements and their appearances in collections.
15
+
16
+ == FEATURES/PROBLEMS:
17
+
18
+ * Nothing for now
19
+
20
+ == SYNOPSIS:
21
+
22
+ # Creating a multiset
23
+ Set[:a,:b,:c,:b,:b,:c] # => #<Set: {:b, :c, :a}>
24
+ Multiset[:a,:b,:c,:b,:b,:c] # => #<Multiset:#3 :b, #2 :c, #1 :a>
25
+
26
+ # Counting the appearances of characters in a string
27
+ m = Multiset.new
28
+ "abracadabra".each_char do |c| # replace with 'each_byte' in Ruby 1.8.6 or before
29
+ m << c
30
+ end
31
+ p m
32
+ # => #<Multiset:#5 "a", #2 "b", #2 "r", #1 "c", #1 "d">
33
+
34
+ # The same
35
+ Multiset.new("abracadabra".split(//))
36
+ # => #<Multiset:#5 "a", #2 "b", #2 "r", #1 "c", #1 "d">
37
+
38
+ # The same, but available with Ruby 1.8.7 or after
39
+ Multiset.new("abracadabra".each_char)
40
+ # => #<Multiset:#5 "a", #2 "b", #2 "r", #1 "c", #1 "d">
41
+
42
+ See also: http://maraigue.hhiro.net/multiset/reverseref.en.html
43
+
44
+ == REQUIREMENTS:
45
+
46
+ No specific external libraries/tools are required.
47
+
48
+ == INSTALL:
49
+
50
+ gem install multiset
51
+
52
+ == DEVELOPERS:
53
+
54
+ After checking out the source, run:
55
+
56
+ $ rake newb
57
+
58
+ This task will install any missing dependencies, run the tests/specs,
59
+ and generate the RDoc.
60
+
61
+ == LICENSE:
62
+
63
+ (The MIT License)
64
+
65
+ Copyright (c) 2008-2012 H.Hiro (Maraigue)
66
+
67
+ Permission is hereby granted, free of charge, to any person obtaining
68
+ a copy of this software and associated documentation files (the
69
+ 'Software'), to deal in the Software without restriction, including
70
+ without limitation the rights to use, copy, modify, merge, publish,
71
+ distribute, sublicense, and/or sell copies of the Software, and to
72
+ permit persons to whom the Software is furnished to do so, subject to
73
+ the following conditions:
74
+
75
+ The above copyright notice and this permission notice shall be
76
+ included in all copies or substantial portions of the Software.
77
+
78
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
79
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
80
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
81
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
82
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
83
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
84
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile CHANGED
@@ -1,50 +1,23 @@
1
- require 'rubygems'
2
- require 'bundler'
3
- begin
4
- Bundler.setup(:default, :development)
5
- rescue Bundler::BundlerError => e
6
- $stderr.puts e.message
7
- $stderr.puts "Run `bundle install` to install missing gems"
8
- exit e.status_code
9
- end
10
- require 'rake'
11
-
12
- require 'jeweler'
13
- Jeweler::Tasks.new do |gem|
14
- # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
- gem.name = "multiset"
16
- gem.homepage = "http://github.com/maraigue/multiset"
17
- gem.license = "MIT"
18
- gem.summary = %Q{Multiset library for Ruby}
19
- gem.description = %Q{Ruby implementation of multiset. Unlike ordinary set(see Ruby documentation for "set" library), multiset can contain two or more same items.}
20
- gem.email = "main@hhiro.net"
21
- gem.authors = ["H.Hiro(Maraigue)"]
22
- # Include your dependencies below. Runtime dependencies are required when using your gem,
23
- # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
- # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
- # gem.add_development_dependency 'rspec', '> 1.2.3'
26
- end
27
- Jeweler::RubygemsDotOrgTasks.new
1
+ # -*- ruby -*-
28
2
 
29
- require 'rspec/core'
30
- require 'rspec/core/rake_task'
31
- RSpec::Core::RakeTask.new(:spec) do |spec|
32
- spec.pattern = FileList['spec/**/*_spec.rb']
33
- end
3
+ require 'rubygems'
4
+ require 'hoe'
34
5
 
35
- RSpec::Core::RakeTask.new(:rcov) do |spec|
36
- spec.pattern = 'spec/**/*_spec.rb'
37
- spec.rcov = true
38
- end
6
+ # Hoe.plugin :compiler
7
+ # Hoe.plugin :gem_prelude_sucks
8
+ # Hoe.plugin :inline
9
+ # Hoe.plugin :racc
10
+ # Hoe.plugin :rcov
11
+ # Hoe.plugin :rubyforge
39
12
 
40
- task :default => :spec
13
+ Hoe.spec 'multiset' do
14
+ # HEY! If you fill these out in ~/.hoe_template/Rakefile.erb then
15
+ # you'll never have to touch them again!
16
+ # (delete this comment too, of course)
41
17
 
42
- require 'rake/rdoctask'
43
- Rake::RDocTask.new do |rdoc|
44
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
18
+ developer('H.Hiro(Maraigue)', 'main@hhiro.net')
45
19
 
46
- rdoc.rdoc_dir = 'rdoc'
47
- rdoc.title = "multiset #{version}"
48
- rdoc.rdoc_files.include('README*')
49
- rdoc.rdoc_files.include('lib/**/*.rb')
20
+ # self.rubyforge_name = 'multisetx' # if different than 'multiset'
50
21
  end
22
+
23
+ # vim: syntax=ruby
@@ -0,0 +1,480 @@
1
+ #!/usr/bin/env ruby
2
+ # -*- coding: utf-8 -*-
3
+
4
+ require "multiset"
5
+
6
+ #==概要(Basic information)
7
+ #
8
+ #Rubyによる多重連想配列(マルチマップ)の実装です。
9
+ #通常の連想配列(Rubyでは"Hash"クラス)と異なり、多重連想配列は
10
+ #1つのキーに対して複数の要素が存在し得ます。
11
+ #
12
+ #メソッド名は基本的にHashクラスに合わせてあります。またHashクラスが持つ
13
+ #メソッドの大部分を実装していますが、いくつか未実装なものもあります。
14
+ #
15
+ #Ruby implementation of multimap.
16
+ #Unlike ordinary map, also known as associative array
17
+ #(see Ruby documentation for "Hash" class),
18
+ #multimap can contain two or more items for a key.
19
+ #
20
+ #Most methods' names are same as those of Hash class, and all other than
21
+ #a few methods in Hash class is implemented on Multimap class.
22
+
23
+ class Multimap
24
+ include Enumerable
25
+
26
+ #--
27
+ # Constructors
28
+ #++
29
+
30
+ # 新しい多重連想配列を生成します。Hash#newと異なり、デフォルト値は
31
+ # 設定できません。
32
+ #
33
+ # Generates a new multimap. Different from Hash#new , you can not
34
+ # specify default value.
35
+ def initialize
36
+ @assoc = Hash.new{ |hash, key| hash[key] = Multiset.new }
37
+ end
38
+
39
+ # Removes all keys in @assoc if the value associated with key is
40
+ # empty multiset.
41
+ def cleanup # :nodoc:
42
+ @assoc.reject!{ |key, value_list| value_list.empty? }
43
+ end
44
+ private :cleanup
45
+
46
+ # キー<code>key</code>に対応する値(複数存在しうる)を、
47
+ # Multisetとして返します。Hash#fetchの場合と異なり、キーに対応する
48
+ # 値が存在しない場合の扱いを指定することはできません。
49
+ # (そのような場合、空のMultisetが返ります。)
50
+ #
51
+ # Returns values associated with <code>key</code> with format of
52
+ # Multiset. Different from Hash#fetch, you can not specify
53
+ # a value or a process when <code>key</code> has not associated with
54
+ # any value. If <code>key</code> has not associated with any value,
55
+ # Multimap#fetch returns empty Multiset.
56
+ def fetch(key)
57
+ @assoc[key]
58
+ end
59
+ alias :[] :fetch
60
+
61
+ # キー<code>key</code>に対応する値(複数存在しうる)を
62
+ # <code>value_list</code>で置き換えます。この際、
63
+ # <code>value_list</code>はMultiset.parseを用いてMultisetに変換されます。
64
+ #
65
+ # <code>value_list</code>を返します。
66
+ #
67
+ # Sets values associated with <code>key</code> to <code>value_list</code>.
68
+ # <code>value_list</code> is converted to a Multiset by Multiset.parse .
69
+ #
70
+ # Returns <code>value_list</code>.
71
+ def store(key, value_list)
72
+ if value_list.class == Multiset
73
+ @assoc[key] = value_list.dup
74
+ else
75
+ @assoc[key] = Multiset.parse(value_list)
76
+ end
77
+ value_list
78
+ end
79
+ alias :[]= :store
80
+
81
+ # <code>self</code>が<code>other</code>と等しいかどうかを返します。
82
+ #
83
+ # Returns whether <code>self</code> is equal to <code>other</code>.
84
+ def ==(other)
85
+ return false unless other.instance_of?(Multimap)
86
+ @assoc == other.to_hash
87
+ end
88
+
89
+ # <code>self</code>を<code>Hash</code>に変換して返します。
90
+ # 生成されるハッシュの構造については、Hash#to_multimapをご覧下さい。
91
+ # その際、返されるハッシュにおいて値はすべてMultimap型となります。
92
+ #
93
+ # Converts <code>self</code> to a <code>Hash</code>.
94
+ # See Hash#to_multimap about format of generated hash.
95
+ # All values in the returned hash are multimaps.
96
+ def to_hash
97
+ @assoc.dup
98
+ end
99
+
100
+ # <code>self</code>に格納された要素をすべて削除します。
101
+ # <code>self</code>を返します。
102
+ #
103
+ # Removes all elements stored in <code>self</code>.
104
+ # Returns <code>self</code>.
105
+ def clear
106
+ @assoc.clear
107
+ end
108
+
109
+ # <code>self</code>の複製を生成して返します。
110
+ #
111
+ # Returns duplicated <code>self</code>.
112
+ def dup
113
+ @assoc.to_multimap
114
+ end
115
+
116
+ # <code>self</code>の内容を<code>other</code>のものに置き換えます。
117
+ # <code>self</code>を返します。
118
+ #
119
+ # Replaces <code>self</code> by <code>other</code>.
120
+ # Returns <code>self</code>.
121
+ def replace(other)
122
+ @assoc.clear
123
+ other.each_pair_with do |key, a_value, count|
124
+ @assoc[key].add a_value, count
125
+ end
126
+ self
127
+ end
128
+
129
+ # <code>key</code>に割り当てられた全ての値を削除し、その値を
130
+ # Multisetとして返します。
131
+ #
132
+ # Deletes all values associated with <code>key</code>, and returns
133
+ # those values as a Multiset.
134
+ def delete(key)
135
+ ret = @assoc[key]
136
+ @assoc.delete(key)
137
+ ret
138
+ end
139
+
140
+ # delete_ifと同じですが、<code>self</code>自身からはキーと値の組を
141
+ # 削除せず、要素が削除された結果の多重連想配列を新たに生成して
142
+ # 返します。
143
+ #
144
+ # Same as delete_if, but generates a new Multimap whose pairs of
145
+ # key and value are deleted, instead of deleting pairs in
146
+ # <code>self</code>.
147
+ def reject(&block) # :yields: key, single_value
148
+ ret = self.dup
149
+ ret.delete_if &block
150
+ ret
151
+ end
152
+
153
+ # ブロックに<code>self</code>のキーと値の組(値は1つ)を順次与え、
154
+ # 結果が真であった組をすべて削除します。
155
+ # <code>self</code>を返します。
156
+ #
157
+ # Gives all pairs of a key and single value in <code>self</code>
158
+ # to given block, and deletes that element if the block returns true.
159
+ # Returns <code>self</code>.
160
+ def delete_if(&block) # :yields: key, single_value
161
+ cleanup
162
+ @assoc.each_pair do |key, value_list|
163
+ value_list.delete_if{ |single_value|
164
+ block.call(key, single_value)
165
+ }
166
+ end
167
+ self
168
+ end
169
+
170
+ # delete_ifと同じですが、キーと値の組が1つも削除されなければ
171
+ # <code>nil</code>を返します。
172
+ #
173
+ # Same as delete_if, but returns <code>nil</code> if no pair of
174
+ # key and value is deleted.
175
+ def reject!(&block) # :yields: key, single_value
176
+ cleanup
177
+ ret = nil
178
+ @assoc.each_pair do |key, value_list|
179
+ ret = self if value_list.reject!{ |single_value|
180
+ block.call(key, single_value)
181
+ }
182
+ end
183
+ ret
184
+ end
185
+
186
+ # rejectと同じですが、ブロックへの引数が(キー、キーに割り当てられた値、
187
+ # その値がキーに割り当てられている個数)の3つの組で与えられます。
188
+ #
189
+ # Same as reject, but arguments given to block is the tuple of three:
190
+ # (key, one value associated with the key, numbers of that value
191
+ # associated with the key).
192
+ def reject_with(&block) # :yields: key, a_value, count
193
+ ret = self.dup
194
+ ret.delete_with &block
195
+ ret
196
+ end
197
+
198
+ # delete_ifと同じですが、ブロックへの引数が(キー、キーに割り当てられた値、
199
+ # その値がキーに割り当てられている個数)の3つの組で与えられます。
200
+ #
201
+ # Same as delete_if, but arguments given to block is the tuple of three:
202
+ # (key, one value associated with the key, numbers of that value
203
+ # associated with the key).
204
+ def delete_with(&block) # :yields: key, a_value, count
205
+ cleanup
206
+ @assoc.each_pair do |key, value_list|
207
+ value_list.delete_with{ |a_value, count|
208
+ block.call(key, a_value, count)
209
+ }
210
+ end
211
+ self
212
+ end
213
+
214
+ # <code>self</code>のすべてのキーと値の組について繰り返します。
215
+ # <code>self</code>を返します。
216
+ #
217
+ # Iterates for each pair of a key and a value in <code>self</code>.
218
+ # Returns <code>self</code>.
219
+ def each_pair
220
+ cleanup
221
+ @assoc.each_pair do |key, value_list|
222
+ value_list.each do |single_value|
223
+ yield key, single_value
224
+ end
225
+ end
226
+ self
227
+ end
228
+ alias :each :each_pair
229
+
230
+ # <code>self</code>のすべてのキーと値の組について、
231
+ # ブロックに(キー、キーに割り当てられた値、その値が割り当てられた数)
232
+ # の組を与えながら繰り返します。<code>self</code>を返します。
233
+ #
234
+ # Iterates for each pair of a key and a value in <code>self</code>,
235
+ # giving the tuple of three to block:
236
+ # (key, one value associated with the key, numbers of that value
237
+ # associated with the key). Returns <code>self</code>.
238
+ def each_pair_with
239
+ cleanup
240
+ @assoc.each_pair do |key, value_list|
241
+ value_list.each_pair do |a_value, count|
242
+ yield key, a_value, count
243
+ end
244
+ end
245
+ self
246
+ end
247
+
248
+ # <code>self</code>のすべてのキーと、そのキーに割り当てられた
249
+ # すべての値(Multisetで与えられる)の組について繰り返します。
250
+ # <code>self</code>を返します。
251
+ #
252
+ # Iterates for each pair of a key and all values associated with the key
253
+ # (list of values is given as Multiset) in <code>self</code>.
254
+ # Returns <code>self</code>.
255
+ def each_pair_list(&block) # :yields: key, value_list
256
+ cleanup
257
+ @assoc.each_pair &block
258
+ end
259
+
260
+
261
+ # <code>self</code>のすべてのキーについて繰り返します。
262
+ # <code>self</code>を返します。
263
+ #
264
+ # Iterates for each key in <code>self</code>. Returns <code>self</code>.
265
+ def each_key(&block) # :yields: key
266
+ cleanup
267
+ @assoc.each_key &block
268
+ end
269
+
270
+ # <code>self</code>のすべての値について繰り返します。
271
+ # <code>self</code>を返します。
272
+ #
273
+ # Iterates for each value in <code>self</code>. Returns <code>self</code>.
274
+ def each_value(&block) # :yields: single_value
275
+ cleanup
276
+ @assoc.each_value do |value_list|
277
+ value_list.each &block
278
+ end
279
+ end
280
+
281
+ # <code>self</code>のすべてのキーを、配列として返します。
282
+ #
283
+ # Returns an array in which keys in <code>self</code> are stored.
284
+ def keys
285
+ cleanup
286
+ @assoc.keys
287
+ end
288
+
289
+
290
+ # <code>self</code>のすべての値を、Multisetとして返します。
291
+ #
292
+ # Returns a Multiset in which values in <code>self</code> are stored.
293
+ def values
294
+ cleanup
295
+ ret = Multiset.new
296
+ @assoc.each_value do |value_list|
297
+ ret.merge! value_list
298
+ end
299
+ ret
300
+ end
301
+
302
+ # <code>self</code>に要素がないかどうかを返します。
303
+ #
304
+ # Returns whether <code>self</code> has no element.
305
+ def empty?
306
+ cleanup
307
+ @assoc.empty?
308
+ end
309
+
310
+ # <code>self</code>にキー<code>key</code>かあるかどうかを返します。
311
+ #
312
+ # Returns whether <code>self</code> has a key <code>key</code>.
313
+ def has_key?(key)
314
+ cleanup
315
+ @assoc.has_key?(key)
316
+ end
317
+ alias :key? :has_key?
318
+ alias :include? :has_key?
319
+ alias :member? :has_key?
320
+
321
+ # <code>self</code>に値<code>value</code>かあるかどうかを返します。
322
+ #
323
+ # Returns whether <code>self</code> has a value <code>value</code>.
324
+ def has_value?(value)
325
+ self.values.items.include?(value)
326
+ end
327
+ alias :value? :has_value?
328
+
329
+ # <code>self</code>から値が<code>value</code>であるような要素を
330
+ # 検索し、それに対応するキーを返します。該当するキーが複数存在する場合、
331
+ # そのうちの1つを返します。該当するキーが存在しなければ
332
+ # <code>nil</code>を返します。
333
+ #
334
+ # Search a pair of key and value from <code>self</code> such that
335
+ # the value is equal to the argument <code>value</code>.
336
+ # If two or keys are matched, returns one of them.
337
+ # If no key is matched, returns nil.
338
+ def key(value)
339
+ self.each_pair_with do |key, a_value, count|
340
+ return key if value == a_value
341
+ end
342
+ nil
343
+ end
344
+ alias :index :key
345
+
346
+ # <code>self</code>から<code>key_list</code>の各キーに対応する値
347
+ # (Multiset型)を取り出し、それらを配列として返します。
348
+ # すなわち、Multisetを要素とする配列を返します。
349
+ #
350
+ # Gets values (instances of Multiset) of <code>self</code>
351
+ # associated with <code>key_list</code>, and returns those values
352
+ # as an array. i.e. returns an array whose elements are multisets.
353
+ def values_at(*key_list)
354
+ key_list.map{ |key| self[key] }
355
+ end
356
+ alias :indexes :values_at
357
+ alias :indices :values_at
358
+
359
+ # <code>self</code>のキーと値を入れ替えたMultimapを返します。
360
+ # 例えばキー:aに対応する値が2つの:xと1つの:yであれば、変換結果は
361
+ # キー:xに:aが2つ、キー:yに:aが1つ対応するMultimapです。
362
+ #
363
+ # Returns a Multimap whose keys are values in <code>self</code>, and
364
+ # values are keys in <code>self</code>. For example,
365
+ # If <code>self</code> has a key :a associated with two :x and one :y,
366
+ # returned multimap has two keys :x and :y, and their values are
367
+ # two :a and one :a respectively.
368
+ def invert
369
+ ret = Multimap.new
370
+ self.each_pair_with do |key, a_value, count|
371
+ ret[a_value].add key, count
372
+ end
373
+ ret
374
+ end
375
+
376
+ # <code>self</code>に含まれている要素数を返します。
377
+ #
378
+ # Returns number of all elements in <code>self</code>.
379
+ def size
380
+ ret = 0
381
+ self.each_pair_with{ |key, a_value, count| ret += count }
382
+ ret
383
+ end
384
+ alias :length :size
385
+
386
+ # <code>self</code>に<code>other</code>の要素を追加します。
387
+ # <code>self</code>を返します。
388
+ #
389
+ # Add elements in <code>other</code> to <code>self</code>.
390
+ # Returns <code>self</code>.
391
+ def merge!(other)
392
+ other.each_pair_with do |key, a_value, count|
393
+ self[key].add a_value, count
394
+ end
395
+ self
396
+ end
397
+
398
+ # <code>self</code>と<code>other</code>の要素を合わせた多重集合を返します。
399
+ #
400
+ # Returns merged multiset of <code>self</code> and <code>other</code>.
401
+ def merge(other)
402
+ ret = self.dup
403
+ ret.merge! other
404
+ end
405
+ alias :+ :merge
406
+
407
+ def to_s(delim = "\n") # :nodoc:
408
+ cleanup
409
+
410
+ buf = ''
411
+ init = true
412
+ @assoc.each_pair do |key, value_list|
413
+ if init
414
+ init = false
415
+ else
416
+ buf += delim
417
+ end
418
+ buf += "#{key.inspect}=>{"
419
+
420
+ init_val = true
421
+ value_list.each_pair do |a_value, count|
422
+ if init_val
423
+ init_val = false
424
+ else
425
+ buf += ", "
426
+ end
427
+ buf += "\##{count} #{a_value.inspect}"
428
+ end
429
+ buf += "}"
430
+ end
431
+ buf
432
+ end
433
+
434
+ def inspect # :nodoc:
435
+ buf = "#<Multimap:"
436
+ buf += self.to_s(', ')
437
+ buf += '>'
438
+ buf
439
+ end
440
+ end
441
+
442
+ class Hash
443
+ # <code>self</code>を多重連想配列に変換し、その結果を返します。
444
+ # 新しく生成される多重連想配列においてキーに割り当てられる値は、
445
+ # <code>self</code>におけるキーの値をMultiset.parseによって多重集合に
446
+ # 変換したものとなります。
447
+ #
448
+ # (例)キー<code>:a</code>には<code>:x</code>と<code>:y</code>が1個ずつ、
449
+ # キー<code>:b</code>には<code>:x</code>が2個割り当てられた多重連想配列
450
+ #
451
+ # <code>{:a => [:x, :y], :b => [:x, :x]}.to_multimap</code>
452
+ #
453
+ # Generates multiset from <code>self</code>.
454
+ # In generated multiset, values associated with a key are defined by
455
+ # the result of Multiset.parse(values_in_<code>self</code>) .
456
+ #
457
+ # (example)
458
+ # Key <code>:a</code> is associated with values one <code>:x</code> and one <code>:y</code>, and
459
+ # key <code>:b</code> is associated with values two <code>:x</code>
460
+ #
461
+ # <code>{:a => [:x, :y], :b => [:x, :x]}.to_multimap</code>
462
+ def to_multimap
463
+ ret = Multimap.new
464
+ self.each_pair{ |key, val| ret[key] = val }
465
+ ret
466
+ end
467
+
468
+ # <code>self</code>を多重連想配列に変換し、その結果を返します。
469
+ # 新しく生成される多重連想配列においてキーに割り当てられる値は、
470
+ # <code>self</code>に含まれる1要素のみです。
471
+ #
472
+ # Generates multiset from <code>self</code>.
473
+ # In generated multiset, only one value is associated with a key
474
+ # (value in <code>self</code>).
475
+ def multimap
476
+ ret = Multimap.new
477
+ self.each_pair{ |key, val| ret[key] = Multiset[val] }
478
+ ret
479
+ end
480
+ end