multiset 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,757 +0,0 @@
1
- #==概要(Basic information)
2
- #
3
- #Rubyによる多重集合(マルチセット)の実装です。
4
- #通常の集合(Rubyでは"set"ライブラリ)と異なり、多重集合は
5
- #同一の要素を複数格納することができます。
6
- #
7
- #メソッド名は基本的にSetクラスに合わせてあります。またSetクラスが持つ
8
- #メソッドの大部分を実装していますが、いくつか未実装なものもあります。
9
- #
10
- #Ruby implementation of multiset.
11
- #Unlike ordinary set(see Ruby documentation for "set" library),
12
- #multiset can contain two or more same items.
13
- #
14
- #Most methods' names are same as those of Set class, and all other than
15
- #a few methods in Set class is implemented on Multiset class.
16
- #
17
- #* <code>Set[:a,:b,:c,:b,:b,:c] => #<Set: {:b, :c, :a}></code>
18
- #* <code>Multiset[:a,:b,:c,:b,:b,:c] => #<Multiset:<tt>#</tt>3 :b, <tt>#</tt>2 :c, <tt>#</tt>1 :a></code>
19
-
20
- class Multiset
21
- include Enumerable
22
- @@parse_string = true
23
-
24
- #--
25
- # Constructors
26
- #++
27
-
28
- # <code>list</code>に含まれる要素からなる多重集合を生成します。
29
- # <code>list</code>を省略した場合、空の多重集合を生成します。
30
- #
31
- # <code>list</code>には<code>Enumerable</code>であるオブジェクトのみ
32
- # 指定できます。そうでない場合、例外<code>ArgumentError</code>が
33
- # 発生します。
34
- #
35
- # Generates a multiset from items in <code>list</code>.
36
- # If <code>list</code> is omitted, returns empty multiset.
37
- #
38
- # <code>list</code> must be <code>Enumerable</code>. If not,
39
- # <code>ArgumentError</code> is raised.
40
- def initialize(list = nil)
41
- @items = {}
42
- if list.kind_of?(Enumerable)
43
- list.each{ |item| add item }
44
- elsif list != nil
45
- raise ArgumentError, "Item list must include 'Enumerable' module"
46
- end
47
- end
48
-
49
- # <code>list</code>に含まれる要素からなる多重集合を生成します。
50
- # <code>new</code>を用いる場合と異なり、引数の1つ1つが多重集合の要素になります。
51
- #
52
- # 主に多重集合のリテラルを生成するのに用います。
53
- #
54
- # Generates a multiset from items in <code>list</code>.
55
- # Unlike using <code>new</code>, each argument is one item in generated multiset.
56
- #
57
- # This method is mainly used when you generate literal of multiset.
58
- def Multiset.[](*list)
59
- Multiset.new(list)
60
- end
61
-
62
- # <code>object</code>を多重集合に変換し生成します。
63
- # * <code>object</code>がMultisetのインスタンスである場合、
64
- # その複製を返します。
65
- # * <code>object</code>がMultisetのインスタンスでなく、
66
- # かつ<code>each_pair</code>メソッドを持っている場合、
67
- # <code>each_pair</code>から渡される2つの引数について、前者を要素、
68
- # 後者をその個数とした多重集合を生成します。Hash#to_multisetも
69
- # ご覧下さい。
70
- # * <code>object</code>が<code>each_pair</code>メソッドを持っておらず、
71
- # かつ<code>Enumerable</code>である場合は、Multiset#newと同じ結果です。
72
- # * それ以外の場合は、例外<code>ArgumentError</code>が発生します。
73
- #
74
- # Generates a multiset converting <code>object</code>.
75
- # * If <code>object</code> is an instance of Multiset, returns
76
- # duplicated <code>object</code>.
77
- # * If <code>object</code> is not an instance of Multiset and has
78
- # the method <code>each_pair</code>,
79
- # for each pair of two arguments from <code>each_pair</code>,
80
- # first argument becomes item in multiset and second argument
81
- # becomes its number. See also Hash#to_multiset .
82
- # * If <code>object</code> does not have the method <code>each_pair</code>
83
- # and <code>object</code> includes <code>Enumerable</code>, this method
84
- # results equal to Multiset#new .
85
- # * Otherwise, <code>ArgumentError</code> is raised.
86
- def Multiset.parse(object)
87
- if !@@parse_string && object.kind_of?(String)
88
- raise ArgumentError, "Multiset.parse can not parse strings"
89
- end
90
- Multiset.parse_force(object)
91
- end
92
-
93
- # Multiset.parseと同様ですが、挙動がMultiset.parse_stringの設定に
94
- # 影響されません(<code>Multiset.parse_string(true)</code>の場合と
95
- # 同様とみなします)。
96
- #
97
- # Same as Multiset.parse, but this method is not affected
98
- # by the setting of Multiset.parse_string (treats
99
- # <code>Multiset.parse_string(true)</code>) .
100
- def Multiset.parse_force(object)
101
- if object.instance_of?(Multiset)
102
- ret = object.dup
103
- else
104
- ret = Multiset.new
105
- if defined? object.each_pair
106
- object.each_pair{ |item, count| ret.add item, count }
107
- elsif object.kind_of?(Enumerable)
108
- object.each{ |item| ret.add item }
109
- else
110
- raise ArgumentError, "Source of Multiset must have 'each_pair' method or include 'Enumerable' module"
111
- end
112
- end
113
- ret
114
- end
115
-
116
- # Multiset.parseの引数にStringを渡すことを許すか指定します。
117
- #
118
- # StringはEnumerableなので、Multiset.parseでは引数として文字列を
119
- # 渡すこともできます。しかしこれはバグの危険性があるため、
120
- # このメソッドで禁止することができます。
121
- #
122
- # <code>boolean</code>にはtrueおよびfalseが指定できます。
123
- # falseを設定した場合、Multiset.parseやMultimap#[]=などで
124
- # 文字列を直接指定した場合に<code>ArgumentError</code>が発生します。
125
- # デフォルト値は<code>true</code>です。
126
- #
127
- # <code>boolean</code>を省略した場合は、現在のこの値がtrueか
128
- # falseかを返します。
129
- #
130
- # この値はクラス変数で管理されているので、一度変更するとすべての
131
- # インスタンスに影響が及びます。
132
- #
133
- # Allows or prohibits Strings from being arguments of Multiset.parse .
134
- #
135
- # String includes module Enumerable, therefore you can give a string as
136
- # an argument of Multiset.parse . But this may cause bugs,
137
- # so you can prohibit this.
138
- #
139
- # <code>boolean</code> can be true or false. If this value is false,
140
- # <code>ArgumentError</code> is raised whenever you specify a string
141
- # as an argument of Multiset.parse , Multimap#[]= , and so on.
142
- # This value is <code>true</code> by default.
143
- #
144
- # If <code>boolean</code> is not specified, returns current value
145
- # (true or false).
146
- #
147
- # This value is stored in class variable, therefore this value has
148
- # effect for all instances of Multiset.
149
- def Multiset.parse_string(boolean = nil)
150
- case boolean
151
- when true, false
152
- @@parse_string = boolean
153
- when nil
154
- else
155
- raise ArgumentError, "Argument must be true or false"
156
- end
157
- @@parse_string
158
- end
159
-
160
- # Same as Multiset.parse_string
161
- def Multiset.parse_string?(boolean = nil)
162
- Multiset.parse_string boolean
163
- end
164
-
165
- # <code>self</code>の複製を生成して返します。
166
- #
167
- # Returns duplicated <code>self</code>.
168
- def dup
169
- @items.to_multiset
170
- end
171
-
172
- # <code>self</code>を<code>Hash</code>に変換して返します。
173
- # 生成されるハッシュの構造については、Hash#to_multisetをご覧下さい。
174
- #
175
- # Converts <code>self</code> to a <code>Hash</code>.
176
- # See Hash#to_multiset about format of generated hash.
177
- def to_hash
178
- @items.dup
179
- end
180
-
181
- # <code>self</code>を通常の集合(Ruby標準添付の<code>Set</code>)に
182
- # 変換したものを返します。
183
- #
184
- # このメソッドを呼び出すと、<code>require "set"</code>が行われます。
185
- #
186
- # なおSetをMultisetに変換するには、<code>Multiset.new(instance_of_set)</code>で
187
- # 可能です。
188
- #
189
- # Converts <code>self</code> to ordinary set
190
- # (The <code>Set</code> class attached to Ruby by default).
191
- #
192
- # <code>require "set"</code> is performed when this method is called.
193
- #
194
- # To convert Set to Multiset, use <code>Multiset.new(instance_of_set)</code>.
195
- def to_set
196
- require "set"
197
- Set.new(@items.keys)
198
- end
199
-
200
- # <code>self</code>を配列に変換して返します。
201
- #
202
- # Converts <code>self</code> to an array.
203
- def to_a
204
- ret = []
205
- @items.each_pair do |item, count|
206
- ret.concat Array.new(count, item)
207
- end
208
- ret
209
- end
210
-
211
- def hash # :nodoc:
212
- val = 0
213
- @items.each_pair do |item, count|
214
- val += item.hash * count
215
- end
216
- val
217
- end
218
-
219
- def eql?(other) # :nodoc:
220
- if self.hash == other.hash
221
- self == other
222
- else
223
- false
224
- end
225
- end
226
-
227
- # <code>self</code>の内容を<code>other</code>のものに置き換えます。
228
- # <code>self</code>を返します。
229
- #
230
- # Replaces <code>self</code> by <code>other</code>.
231
- # Returns <code>self</code>.
232
- def replace(other)
233
- @items.clear
234
- other.each_pair do |item, count|
235
- self.renew_count(item, count)
236
- end
237
- self
238
- end
239
-
240
- # <code>self</code>に含まれている要素数を返します。
241
- #
242
- # Returns number of all items in <code>self</code>.
243
- def size
244
- @items.inject(0){ |sum, item| sum += item[1] }
245
- end
246
- alias length size
247
-
248
- # <code>self</code>に要素がないかどうかを返します。
249
- #
250
- # Returns whether <code>self</code> has no item.
251
- def empty?
252
- @items.empty?
253
- end
254
-
255
- # <code>self</code>に含まれている要素(重複は除く)からなる配列を返します。
256
- #
257
- # Returns an array with all items in <code>self</code>, without duplication.
258
- def items
259
- @items.keys
260
- end
261
-
262
- # <code>self</code>の要素をすべて削除します。
263
- # <code>self</code>を返します。
264
- #
265
- # Deletes all items in <code>self</code>.
266
- # Returns <code>self</code>.
267
- def clear
268
- @items.clear
269
- self
270
- end
271
-
272
- # <code>item</code>が<code>self</code>中に含まれているかを返します。
273
- #
274
- # Returns whether <code>self</code> has <code>item</code>.
275
- def include?(item)
276
- @items.has_key?(item)
277
- end
278
- alias member? include?
279
-
280
- # <code>self</code>中に含まれる<code>item</code>の個数を返します。
281
- #
282
- # Returns number of <code>item</code>s in <code>self</code>.
283
- def count(item)
284
- @items.has_key?(item) ? @items[item] : 0
285
- end
286
-
287
- # <code>self</code>に含まれるすべての要素について繰り返します。
288
- # <code>self</code>を返します。
289
- #
290
- # Iterates for each item in <code>self</code>.
291
- # Returns <code>self</code>.
292
- def each
293
- @items.each_pair do |item, count|
294
- count.times{ yield item }
295
- end
296
- self
297
- end
298
-
299
- # <code>self</code>に含まれるすべての要素について、重複を許さずに繰り返します。
300
- # <code>self</code>を返します。
301
- #
302
- # Iterates for each item in <code>self</code>, without duplication.
303
- # Returns <code>self</code>.
304
- def each_item(&block) # :yields: item
305
- @items.each_key(&block)
306
- self
307
- end
308
-
309
- # <code>self</code>に含まれるすべての要素とその個数について繰り返します。
310
- # <code>self</code>を返します。
311
- #
312
- # Iterates for each pair of item and its number in <code>self</code>.
313
- # Returns <code>self</code>.
314
- def each_pair(&block) # :yields: item, count
315
- @items.each_pair(&block)
316
- self
317
- end
318
-
319
- # <code>self</code>に含まれる<code>item</code>の個数を<code>number</code>個にします。
320
- # <code>number</code>が負の数であった場合は、<code>number = 0</code>とみなします。
321
- # 成功した場合は<code>self</code>を、失敗した場合は<code>nil</code>を返します。
322
- #
323
- # Sets number of <code>item</code> to <code>number</code> in <code>self</code>.
324
- # If <code>number</code> is negative, treats as <code>number = 0</code>.
325
- # Returns <code>self</code> if succeeded, <code>nil</code> otherwise.
326
- def renew_count(item, number)
327
- return nil if number == nil
328
- n = number.to_i
329
- if n > 0
330
- @items[item] = n
331
- else
332
- @items.delete(item)
333
- end
334
- self
335
- end
336
-
337
- # <code>self</code>の各要素をブロックに与え、返り値を集めたものからなる
338
- # 多重集合を生成します。
339
- #
340
- # Gives all items in <code>self</code> to given block,
341
- # and generates a new multiset whose values are returned value from the block.
342
- def map
343
- ret = Multiset.new
344
- self.each do |item|
345
- ret << yield(item)
346
- end
347
- ret
348
- end
349
- alias collect map
350
-
351
- # Multiset#mapと同様ですが、結果として生成される多重集合で<code>self</code>が
352
- # 置き換えられます。<code>self</code>を返します。
353
- #
354
- # Same as Multiset#map, but replaces <code>self</code> by resulting multiset.
355
- # Returns <code>self</code>.
356
- def map!
357
- self.to_a.each do |item|
358
- self.delete(item)
359
- self << yield(item)
360
- end
361
- self
362
- end
363
- alias collect! map!
364
-
365
- # <code>self</code>の要素とその個数の組をブロックに与えます。
366
- # ブロックから2要素の配列を受け取り、前者を要素、後者をその個数とした
367
- # 多重集合を生成します。
368
- #
369
- # Gives all pairs of items and their numbers in <code>self</code> to
370
- # given block. The block must return an array of two items.
371
- # Generates a new multiset whose values and numbers are the first and
372
- # second item of returned array, respectively.
373
- def map_with
374
- ret = Multiset.new
375
- self.each_pair do |item, count|
376
- val = yield(item, count)
377
- ret.add(val[0], val[1])
378
- end
379
- ret
380
- end
381
- alias collect_with map_with
382
-
383
- # Multiset#map_withと同様ですが、結果として生成される多重集合で
384
- # <code>self</code>が置き換えられます。<code>self</code>を返します。
385
- #
386
- # Same as Multiset#map_with, but replaces <code>self</code> by
387
- # resulting multiset. Returns <code>self</code>.
388
- def map_with!
389
- self.to_hash.each_pair do |item, count|
390
- self.delete(item, count)
391
- val = yield(item, count)
392
- self.add(val[0], val[1])
393
- end
394
- self
395
- end
396
- alias collect_with! map_with!
397
-
398
- # <code>self</code>の要素を無作為に1つ選んで返します。
399
- # すべての要素は等確率で選ばれます。
400
- #
401
- # Returns one item in <code>self</code> randomly.
402
- # All items are selected with same probability.
403
- def rand
404
- pos = Kernel.rand(self.size)
405
- @items.each_pair do |item, count|
406
- pos -= count
407
- return item if pos < 0
408
- end
409
- end
410
-
411
- # <code>self</code>と<code>other</code>が持つすべての要素(重複なし)について
412
- # 繰り返し、ブロックの返り値が偽であるものが存在すればその時点でfalseを返します。
413
- # すべての要素について真であればtrueを返します。
414
- #
415
- # このメソッドはsuperset?、subset?、== のために定義されています。
416
- #
417
- # Iterates for each item in <code>self</code> and <code>other</code>,
418
- # without duplication. If the given block returns false, then iteration
419
- # immediately ends and returns false.
420
- # Returns true if the given block returns true for all of iteration.
421
- #
422
- # This method is defined for methods superset?, subset?, ==.
423
- def compare_set_with(other) # :nodoc: :yields: number_in_self, number_in_other
424
- check = self.items.dup
425
- check.concat(other.items)
426
- check.each do |item|
427
- return false unless yield(self.count(item), other.count(item))
428
- end
429
- true
430
- end
431
-
432
- # <code>self</code>が<code>other</code>を含んでいるかどうかを返します。
433
- #
434
- # Returns whether <code>self</code> is a superset of <code>other</code>.
435
- def superset?(other)
436
- unless other.instance_of?(Multiset)
437
- raise ArgumentError, "Argument must be a Multiset"
438
- end
439
- compare_set_with(other){ |s, o| s >= o }
440
- end
441
-
442
- # <code>self</code>が<code>other</code>を真に含んでいるかどうかを返します。
443
- # 「真に」とは、両者が一致する場合は含めないことを示します。
444
- #
445
- # Returns whether <code>self</code> is a proper superset of <code>other</code>.
446
- def proper_superset?(other)
447
- unless other.instance_of?(Multiset)
448
- raise ArgumentError, "Argument must be a Multiset"
449
- end
450
- self.superset?(other) && self != other
451
- end
452
-
453
- # <code>self</code>が<code>other</code>に含まれているかどうかを返します。
454
- #
455
- # Returns whether <code>self</code> is a subset of <code>other</code>.
456
- def subset?(other)
457
- unless other.instance_of?(Multiset)
458
- raise ArgumentError, "Argument must be a Multiset"
459
- end
460
- compare_set_with(other){ |s, o| s <= o }
461
- end
462
-
463
- # <code>self</code>が<code>other</code>に真に含まれているかどうかを返します。
464
- # 「真に」とは、両者が一致する場合は含めないことを示します。
465
- #
466
- # Returns whether <code>self</code> is a proper subset of <code>other</code>.
467
- def proper_subset?(other)
468
- unless other.instance_of?(Multiset)
469
- raise ArgumentError, "Argument must be a Multiset"
470
- end
471
- self.subset?(other) && self != other
472
- end
473
-
474
- # <code>self</code>が<code>other</code>と等しいかどうかを返します。
475
- #
476
- # Returns whether <code>self</code> is equal to <code>other</code>.
477
- def ==(other)
478
- return false unless other.instance_of?(Multiset)
479
- compare_set_with(other){ |s, o| s == o }
480
- end
481
-
482
- # <code>self</code>中に含まれる多重集合を平滑化したものを返します。
483
- #
484
- # Generates a multiset such that multisets in <code>self</code> are flattened.
485
- def flatten
486
- ret = Multiset.new
487
- self.each do |item|
488
- if item.kind_of?(Multiset)
489
- ret += item.flatten
490
- else
491
- ret << item
492
- end
493
- end
494
- ret
495
- end
496
-
497
- # <code>self</code>中に含まれる多重集合を平滑化します。
498
- # 平滑化した多重集合が1つでもあれば<code>self</code>を、
499
- # そうでなければ<code>nil</code>を返します。
500
- #
501
- # Flattens multisets in <code>self</code>.
502
- # Returns <code>self</code> if any item is flattened,
503
- # <code>nil</code> otherwise.
504
- def flatten!
505
- ret = nil
506
- self.to_a.each do |item|
507
- if item.kind_of?(Multiset)
508
- self.delete(item)
509
- self.merge!(item.flatten)
510
- ret = self
511
- end
512
- end
513
- ret
514
- end
515
-
516
- # <code>self</code>に、<code>addcount</code>個の<code>item</code>を追加します。
517
- # 成功した場合は<code>self</code>を、失敗した場合は<code>nil</code>を返します。
518
- #
519
- # Adds <code>addcount</code> number of <code>item</code>s to <code>self</code>.
520
- # Returns <code>self</code> if succeeded, or <code>nil</code> if failed.
521
- def add(item, addcount = 1)
522
- return nil if addcount == nil
523
- a = addcount.to_i
524
- return nil if a <= 0
525
- self.renew_count(item, self.count(item) + a)
526
- end
527
- alias << add
528
-
529
- # <code>self</code>から、<code>delcount</code>個の<code>item</code>を削除します。
530
- # 成功した場合は<code>self</code>を、失敗した場合は<code>nil</code>を返します。
531
- #
532
- # Deletes <code>delcount</code> number of <code>item</code>s
533
- # from <code>self</code>.
534
- # Returns <code>self</code> if succeeded, <code>nil</code> otherwise.
535
- def delete(item, delcount = 1)
536
- return nil if delcount == nil || !self.include?(item)
537
- d = delcount.to_i
538
- return nil if d <= 0
539
- self.renew_count(item, self.count(item) - d)
540
- end
541
-
542
- # <code>self</code>に含まれる<code>item</code>をすべて削除します。
543
- # <code>self</code>を返します。
544
- #
545
- # Deletes all <code>item</code>s in <code>self</code>.
546
- # Returns <code>self</code>.
547
- def delete_all(item)
548
- @items.delete(item)
549
- self
550
- end
551
-
552
- # delete_ifと同じですが、要素が1つも削除されなければ<code>nil</code>を返します。
553
- #
554
- # Same as delete_if, but returns <code>nil</code> if no item is deleted.
555
- def reject!
556
- ret = nil
557
- self.to_a.each do |item|
558
- if yield(item)
559
- ret = self if self.delete(item) == self
560
- end
561
- end
562
- ret
563
- end
564
-
565
- # ブロックに<code>self</code>の要素を順次与え、
566
- # 結果が真であった要素をすべて削除します。
567
- # <code>self</code>を返します。
568
- #
569
- # Gives all items in <code>self</code> to given block,
570
- # and deletes that item if the block returns true.
571
- # Returns <code>self</code>.
572
- def delete_if
573
- self.to_a.each do |item|
574
- @items.delete(item) if yield(item)
575
- end
576
- self
577
- end
578
-
579
- # <code>self</code>に含まれるすべての要素とその個数について、
580
- # その組をブロックに与え、結果が真であった要素をすべて削除します。
581
- # <code>self</code>を返します。
582
- #
583
- # Gives each pair of item and its number to given block,
584
- # and deletes those items if the block returns true.
585
- # Returns <code>self</code>.
586
- def delete_with
587
- @items.each_pair do |item, count|
588
- @items.delete(item) if yield(item, count)
589
- end
590
- self
591
- end
592
-
593
- # <code>self</code>と<code>other</code>の要素を合わせた多重集合を返します。
594
- #
595
- # Returns merged multiset of <code>self</code> and <code>other</code>.
596
- def merge(other)
597
- ret = self.dup
598
- other.each_pair do |item, count|
599
- ret.add(item, count)
600
- end
601
- ret
602
- end
603
- alias + merge
604
-
605
- # <code>self</code>に<code>other</code>の要素を追加します。
606
- # <code>self</code>を返します。
607
- #
608
- # Merges <code>other</code> to <code>self</code>.
609
- # Returns <code>self</code>.
610
- def merge!(other)
611
- other.each_pair do |item, count|
612
- self.add(item, count)
613
- end
614
- self
615
- end
616
-
617
- # <code>self</code>から<code>other</code>の要素を取り除いた多重集合を返します。
618
- #
619
- # Returns multiset such that items in <code>other</code> are removed from <code>self</code>.
620
- def subtract(other)
621
- ret = self.dup
622
- other.each_pair do |item, count|
623
- ret.delete(item, count)
624
- end
625
- ret
626
- end
627
- alias - subtract
628
-
629
- # <code>self</code>から<code>other</code>の要素を削除します。
630
- # <code>self</code>を返します。
631
- #
632
- # Removes items in <code>other</code> from <code>self</code>.
633
- # Returns <code>self</code>.
634
- def subtract!(other)
635
- other.each_pair do |item, count|
636
- self.delete(item, count)
637
- end
638
- self
639
- end
640
-
641
- # <code>self</code>と<code>other</code>の積集合からなる多重集合を返します。
642
- #
643
- # Returns intersection of <code>self</code> and <code>other</code>.
644
- def &(other)
645
- ret = Multiset.new
646
- (self.items & other.items).each do |item|
647
- ret.renew_count(item, [self.count(item), other.count(item)].min)
648
- end
649
- ret
650
- end
651
-
652
- # <code>self</code>と<code>other</code>の和集合からなる多重集合を返します。
653
- #
654
- # Returns union of <code>self</code> and <code>other</code>.
655
- def |(other)
656
- ret = self.dup
657
- other.each_pair do |item, count|
658
- ret.renew_count(item, [self.count(item), count].max)
659
- end
660
- ret
661
- end
662
-
663
- # <code>self</code>の要素を、与えられたブロックからの返り値によって分類します。
664
- # ブロックからの返り値をキーとして値を対応付けたMultimapを返します。
665
- #
666
- # Classify items in <code>self</code> by returned value from block.
667
- # Returns a Multimap whose values are associated with keys. Keys'
668
- # are defined by returned value from given block.
669
- def classify
670
- ret = Multimap.new
671
- self.each do |item|
672
- ret[yield(item)].add(item)
673
- end
674
- ret
675
- end
676
-
677
- # classifyと同様ですが、ブロックには要素とその個数の組が与えられます。
678
- #
679
- # Same as classify, but the pair of item and its number is given to block.
680
- def classify_with
681
- ret = Multimap.new
682
- self.each_pair do |item, count|
683
- ret[yield(item, count)].add(item, count)
684
- end
685
- ret
686
- end
687
-
688
- # <code>self</code>の全要素を(重複を許して)並べた文字列を返します。
689
- # 要素間の区切りは<code>delim</code>の値を用い、
690
- # 各要素の表示形式は与えられたブロックの返り値(なければObject#inspect)を用います。
691
- #
692
- # Lists all items with duplication in <code>self</code>.
693
- # Items are deliminated with <code>delim</code>, and items are
694
- # converted to string in the given block.
695
- # If block is omitted, Object#inspect is used.
696
- def listing(delim = "\n")
697
- buf = ''
698
- init = true
699
- self.each do |item|
700
- if init
701
- init = false
702
- else
703
- buf += delim
704
- end
705
- buf += block_given? ? yield(item).to_s : item.inspect
706
- end
707
- buf
708
- end
709
-
710
- # <code>self</code>の要素と要素数の組を並べた文字列を返します。
711
- # 要素間の区切りは<code>delim</code>の値を用い、
712
- # 各要素の表示形式は与えられたブロックの返り値(なければObject#inspect)を用います。
713
- #
714
- # Lists all items without duplication and its number in <code>self</code>.
715
- # Items are deliminated with <code>delim</code>, and items are
716
- # converted to string in the given block.
717
- # If block is omitted, Object#inspect is used.
718
- def to_s(delim = "\n")
719
- buf = ''
720
- init = true
721
- self.each_pair do |item, count|
722
- if init
723
- init = false
724
- else
725
- buf += delim
726
- end
727
- item_tmp = block_given? ? yield(item) : item.inspect
728
- buf += "\##{count} #{item_tmp}"
729
- end
730
- buf
731
- end
732
-
733
- def inspect # :nodoc:
734
- buf = "#<Multiset:"
735
- buf += self.to_s(', ')
736
- buf += '>'
737
- buf
738
- end
739
- end
740
-
741
- class Hash
742
- # <code>self</code>を多重集合に変換し、その結果を返します。
743
- # キーを要素、キーに対応する値をその要素の要素数とします。
744
- #
745
- # (例)<code>{:a => 4, :b => 2}.to_multiset # :aを4個、:bを2個含む多重集合</code>
746
- #
747
- # Generates multiset from <code>self</code>.
748
- # Keys are treated as elements, and values are number of elements
749
- # in the multiset. For example,
750
- #
751
- # <code>{:a => 4, :b => 2}.to_multiset # Multiset with four :a's and two :b's</code>
752
- def to_multiset
753
- ret = Multiset.new
754
- self.each_pair{ |item, count| ret.renew_count(item, count) }
755
- ret
756
- end
757
- end