Class: Multiset

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/multiset.rb

Overview

概要(Basic information)

Rubyによる多重集合(マルチセット)の実装です。通常の集合(Rubyでは“set”ライブラリ)と異なり、多重集合は同一の要素を複数格納することができます。

メソッド名は基本的にSetクラスに合わせてあります。またSetクラスが持つメソッドの大部分を実装していますが、いくつか未実装なものもあります。

Ruby implementation of multiset. Unlike ordinary set(see Ruby documentation for “set” library), multiset can contain two or more same items.

Most methods’ names are same as those of Set class, and all other than a few methods in Set class is implemented on Multiset class.

  • Set[:a,:b,:c,:b,:b,:c] => #<Set: {:b, :c, :a}>

  • Multiset[:a,:b,:c,:b,:b,:c] => #<Multiset:#3 :b, #2 :c, #1 :a>

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(list = nil) ⇒ Multiset

listに含まれる要素からなる多重集合を生成します。listを省略した場合、空の多重集合を生成します。

listにはEnumerableであるオブジェクトのみ指定できます。そうでない場合、例外ArgumentErrorが発生します。

Generates a multiset from items in list. If list is omitted, returns empty multiset.

list must be Enumerable. If not, ArgumentError is raised.



48
49
50
51
52
53
54
55
# File 'lib/multiset.rb', line 48

def initialize(list = nil)
  @entries = {}
  if list.kind_of?(Enumerable)
    list.each{ |item| add item }
  elsif list != nil
    raise ArgumentError, "Item list must include 'Enumerable' module"
  end
end

Class Method Details

.[](*list) ⇒ Object

listに含まれる要素からなる多重集合を生成します。newを用いる場合と異なり、引数の1つ1つが多重集合の要素になります。

主に多重集合のリテラルを生成するのに用います。

Generates a multiset from items in list. Unlike using new, each argument is one item in generated multiset.

This method is mainly used when you generate literal of multiset.



66
67
68
# File 'lib/multiset.rb', line 66

def Multiset.[](*list)
  Multiset.new(list)
end

.from_lines(str) ⇒ Object

文字列を行単位で区切ってMultisetにします。

Generates a Multiset from string, separated by lines.



117
118
119
# File 'lib/multiset.rb', line 117

def Multiset.from_lines(str)
  Multiset.new(str.enum_for(:each_line))
end

.parse(object) ⇒ Object

objectを多重集合に変換し生成します。

  • objectがMultisetのインスタンスである場合、その複製を返します。

  • objectがMultisetのインスタンスでなく、かつeach_pairメソッドを持っている場合、each_pairから渡される2つの引数について、前者を要素、後者をその個数とした多重集合を生成します。Hash#to_multisetもご覧下さい。

  • objecteach_pairメソッドを持っておらず、かつEnumerableである場合は、Multiset#newと同じ結果です。

  • それ以外の場合は、例外ArgumentErrorが発生します。

Generates a multiset converting object.

  • If object is an instance of Multiset, returns duplicated object.

  • If object is not an instance of Multiset and has the method each_pair, for each pair of two arguments from each_pair, first argument becomes item in multiset and second argument becomes its number. See also Hash#to_multiset .

  • If object does not have the method each_pair and object includes Enumerable, this method results equal to Multiset#new .

  • Otherwise, ArgumentError is raised.



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/multiset.rb', line 94

def Multiset.parse(object)
  if object.kind_of?(String)
    raise ArgumentError, "Multiset.parse can not parse strings. If you would like to store string lines to a multiset, use Multiset.from_lines(string)."
  end
  
  if object.instance_of?(Multiset)
    ret = object.dup
  else
    ret = Multiset.new
    if defined? object.each_pair
      object.each_pair{ |item, count| ret.add item, count }
    elsif object.kind_of?(Enumerable)
      object.each{ |item| ret.add item }
    else
      raise ArgumentError, "Source of Multiset must have 'each_pair' method or include 'Enumerable' module"
    end
  end
  ret
end

.parse_force(object) ⇒ Object

文字列が渡された場合は、Multiset.from_linesと同じ挙動。それ以外の場合は、Multiset.parseと同じ挙動。

If a string is given, it works as Multiset.from_lines, otherwise as Multiset.parse.



126
127
128
129
130
131
132
# File 'lib/multiset.rb', line 126

def Multiset.parse_force(object)
  if object.kind_of?(String)
    Multiset.from_lines(object)
  else
    Multiset.parse(object)
  end
end

Instance Method Details

#&(other) ⇒ Object

selfotherの積集合からなる多重集合を返します。

Returns intersection of self and other.



542
543
544
545
546
547
548
# File 'lib/multiset.rb', line 542

def &(other)
  ret = Multiset.new
  (self.items & other.items).each do |item|
    ret.renew_count(item, [self.count(item), other.count(item)].min)
  end
  ret
end

#==(other) ⇒ Object

selfotherと等しいかどうかを返します。

Returns whether self is equal to other.



480
481
482
483
# File 'lib/multiset.rb', line 480

def ==(other)
  return false unless other.instance_of?(Multiset)
  compare_set_with(other){ |s, o| s == o }
end

#add(item, addcount = 1) ⇒ Object Also known as: <<

selfに、addcount個のitemを追加します。成功した場合はselfを、失敗した場合はnilを返します。

Adds addcount number of items to self. Returns self if succeeded, or nil if failed.



379
380
381
382
383
384
# File 'lib/multiset.rb', line 379

def add(item, addcount = 1)
  return nil if addcount == nil
  a = addcount.to_i
  return nil if a <= 0
  self.renew_count(item, self.count(item) + a)
end

#clearObject

selfの要素をすべて削除します。selfを返します。

Deletes all items in self. Returns self.



248
249
250
251
# File 'lib/multiset.rb', line 248

def clear
  @entries.clear
  self
end

#compare_set_with(other) ⇒ Object

selfotherが持つすべての要素(重複なし)について繰り返し、ブロックの返り値が偽であるものが存在すればその時点でfalseを返します。すべての要素について真であればtrueを返します。

このメソッドはsuperset?、subset?、== のために定義されています。

Iterates for each item in self and other, without duplication. If the given block returns false, then iteration immediately ends and returns false. Returns true if the given block returns true for all of iteration.

This method is defined for methods superset?, subset?, ==.



428
429
430
431
432
433
# File 'lib/multiset.rb', line 428

def compare_set_with(other) # :nodoc: :yields: number_in_self, number_in_other
  (self.items | other.items).each do |item|
    return false unless yield(self.count(item), other.count(item))
  end
  true
end

#count(*item_list) ⇒ Object

self中に含まれるitemの個数を返します。引数を指定しない場合は、Multiset#sizeと同じです。ブロックを指定することもでき、その場合は(重複しない)各要素をブロックに与え、条件を満たした(結果が真であった)要素がMultiset内にいくつ入っているかを数えます。

Returns number of items in self. If the item is omitted, the value is same as Multiset#size. If a block is given, each element (without duplication) is given to the block, and returns the number of elements (including duplication) that returns true in the block.

:call-seq:

count(item)
count{ |item| ... }


333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
# File 'lib/multiset.rb', line 333

def count(*item_list)
  if block_given?
    unless item_list.empty?
      raise ArgumentError, "Both item and block cannot be given"
    end
    
    result = 0
    @entries.each_pair do |i, c|
      result += c if yield(i)
    end
    result
  else
    case item_list.size
    when 0
      self.size
    when 1
      @entries.has_key?(item_list.first) ? @entries[item_list.first] : 0
    else
      raise ArgumentError, "Only one item can be given"
    end
  end
end

#delete(item, delcount = 1) ⇒ Object

selfから、delcount個のitemを削除します。成功した場合はselfを、失敗した場合はnilを返します。

Deletes delcount number of items from self. Returns self if succeeded, nil otherwise.



393
394
395
396
397
398
# File 'lib/multiset.rb', line 393

def delete(item, delcount = 1)
  return nil if delcount == nil || !self.include?(item)
  d = delcount.to_i
  return nil if d <= 0
  self.renew_count(item, self.count(item) - d)
end

#delete_all(item) ⇒ Object

selfに含まれるitemをすべて削除します。selfを返します。

Deletes all items in self. Returns self.



405
406
407
408
# File 'lib/multiset.rb', line 405

def delete_all(item)
  @entries.delete(item)
  self
end

#delete_ifObject

ブロックにselfの要素(重複なし)を順次与え、結果が真であった要素をすべて削除します。selfを返します。

Gives all items in self (without duplication) to given block, and deletes that item if the block returns true. Returns self.



785
786
787
788
789
790
# File 'lib/multiset.rb', line 785

def delete_if
  @entries.each_pair do |item, count|
    self.delete_all(item) if yield(item)
  end
  self
end

#delete_withObject

selfに含まれるすべての要素(重複なし)とその個数について、その組をブロックに与え、結果が真であった要素をすべて削除します。selfを返します。

Gives each pair of (non-duplicate) item and its number to given block, and deletes those items if the block returns true. Returns self.



799
800
801
802
803
804
# File 'lib/multiset.rb', line 799

def delete_with
  @entries.each_pair do |item, count|
    @entries.delete(item) if yield(item, count)
  end
  self
end

#dupObject

selfの複製を生成して返します。

Returns duplicated self.



137
138
139
# File 'lib/multiset.rb', line 137

def dup
  @entries.to_multiset
end

#eachObject

selfに含まれるすべての要素について繰り返します。selfを返します。ブロックが与えられていない場合、Enumeratorを返します。

このメソッドは Enumerable#each の挙動に合わせ、同じ要素を何度もブロックに渡すため、効率が悪いです。Multiset#each_item, Multiset#each_pairの利用もご検討下さい。例えば「“a”が100個入ったMultiset」をeachで繰り返すと100回の処理が行われますが、each_pairなら1回で済みます。

Iterates for each item in self. Returns self. An Enumerator will be returned if no block is given.

This method is ineffective since the same element in the Multiset can be given to the block for many times, same as the behavior of Enumerable#each. Please consider using Multiset#each_item or Multiset#each_pair: for example, a Multiset with 100 times “a” will call the given block for 100 times for Multiset#each, while only once for Multiset#each_pair.



585
586
587
588
589
590
591
592
593
594
# File 'lib/multiset.rb', line 585

def each
  if block_given?
    @entries.each_pair do |item, count|
      count.times{ yield item }
    end
    self
  else
    Enumerator.new(self, :each)
  end
end

#each_item(&block) ⇒ Object

selfに含まれるすべての要素について、重複を許さずに繰り返します。selfを返します。ブロックが与えられていない場合、Enumeratorを返します。

Iterates for each item in self, without duplication. Returns self. An Enumerator will be returned if no block is given.



603
604
605
606
607
608
609
610
# File 'lib/multiset.rb', line 603

def each_item(&block) # :yields: item
  if block
    @entries.each_key(&block)
    self
  else
    @entries.each_key
  end
end

#each_with_count(&block) ⇒ Object Also known as: each_pair

selfに含まれるすべての要素(重複なし)とその個数について繰り返します。selfを返します。ブロックが与えられていない場合、Enumeratorを返します。

Iterates for each pair of (non-duplicated) item and its number in self. Returns self. An Enumerator will be returned if no block is given.



619
620
621
622
623
624
625
626
# File 'lib/multiset.rb', line 619

def each_with_count(&block) # :yields: item, count
  if block
    @entries.each_pair(&block)
    self
  else
    @entries.each_pair
  end
end

#empty?Boolean

selfに要素がないかどうかを返します。

Returns whether self has no item.

Returns:

  • (Boolean)


232
233
234
# File 'lib/multiset.rb', line 232

def empty?
  @entries.empty?
end

#eql?(other) ⇒ Boolean

:nodoc:

Returns:

  • (Boolean)


194
195
196
197
198
199
200
# File 'lib/multiset.rb', line 194

def eql?(other) # :nodoc:
  if self.hash == other.hash
    self == other
  else
    false
  end
end

#find(ifnone = nil, &block) ⇒ Object Also known as: detect

ブロックにselfの要素(重複なし)を順次与え、最初に結果が真であった要素を返します。見つからなかった場合は、ifnoneが指定されている場合は ifnone.call し、そうでなければnilを返します。ブロックを与えなかった場合、そのためのEnumeratorを返します。

Gives all items in self (without duplication) to given block, and returns the first item that makes true the result of the block. If none of the items make it true, ifnone.call is executed if ifnone is specified, otherwise nil is returned. If no block is given, corresponding Enumerator is returned.



844
845
846
847
848
849
850
# File 'lib/multiset.rb', line 844

def find(ifnone = nil, &block) # :yields: item
  if block
    find_(ifnone, &block)
  else
    self.to_enum(:find_, ifnone)
  end
end

#find_all(&block) ⇒ Object Also known as: select

ブロックにselfの要素(重複なし)を順次与え、結果が真であった要素を集めた多重集合を返します。ブロックを与えなかった場合、そのためのEnumeratorを返します。

Gives all items in self (without duplication) to given block, and returns the Multiset by items that makes true the result of the block. If no block is given, corresponding Enumerator is returned.



888
889
890
891
892
893
894
# File 'lib/multiset.rb', line 888

def find_all(&block) # :yields: item
  if block
    find_all_(&block)
  else
    self.to_enum(:find_all_, ifnone)
  end
end

#find_all_with(&block) ⇒ Object Also known as: select_with

Multiset#find_allと同じですが、ブロックにはselfの要素とその個数の組が与えられます。

The same as Multiset#find_all, but pairs of (non-duplicate) items and their counts are given to the block.



909
910
911
912
913
914
915
# File 'lib/multiset.rb', line 909

def find_all_with(&block) # :yields: item
  if block
    find_all_with_(&block)
  else
    self.to_enum(:find_all_with_, ifnone)
  end
end

#find_all_with_(&block) ⇒ Object

:nodoc:



918
919
920
921
922
923
924
# File 'lib/multiset.rb', line 918

def find_all_with_(&block) # :nodoc:
  ret = Multiset.new
  @entries.each_pair do |item, count|
    ret.renew_count(item, count) if yield(item, count)
  end
  ret
end

#find_with(ifnone = nil, &block) ⇒ Object Also known as: detect_with

Multiset#findと同じですが、ブロックにはselfの要素とその個数の組が与えられます。

The same as Multiset#find, but pairs of (non-duplicate) items and their counts are given to the block.



864
865
866
867
868
869
870
# File 'lib/multiset.rb', line 864

def find_with(ifnone = nil, &block) # :yields: item
  if block
    find_with_(ifnone, &block)
  else
    self.to_enum(:find_with_, ifnone)
  end
end

#flattenObject

self中に含まれる多重集合を平滑化したものを返します。

Generates a multiset such that multisets in self are flattened.



707
708
709
710
711
712
713
714
715
716
717
# File 'lib/multiset.rb', line 707

def flatten
  ret = Multiset.new
  self.each do |item|
    if item.kind_of?(Multiset)
      ret += item.flatten
    else
      ret << item
    end
  end
  ret
end

#flatten!Object

self中に含まれる多重集合を平滑化します。平滑化した多重集合が1つでもあればselfを、そうでなければnilを返します。

Flattens multisets in self. Returns self if any item is flattened, nil otherwise.



726
727
728
729
730
731
732
733
734
735
736
# File 'lib/multiset.rb', line 726

def flatten!
  ret = nil
  self.to_a.each do |item|
    if item.kind_of?(Multiset)
      self.delete(item)
      self.merge!(item.flatten)
      ret = self
    end
  end
  ret
end

#grep(pattern) ⇒ Object

patternの条件を満たした(pattern === item)要素のみを集めた多重集合を返します。ブロックが与えられている場合は、さらにその結果を適用した結果を返します。

Collects items in self satisfying pattern (pattern === item). If a block is given, the items are converted by the result of the block.



932
933
934
935
936
937
938
939
940
# File 'lib/multiset.rb', line 932

def grep(pattern)
  ret = Multiset.new
  @entries.each_pair do |item, count|
    if pattern === item
      ret.add((block_given? ? yield(item) : item), count)
    end
  end
  ret
end

#group_byObject Also known as: classify

selfの要素を、与えられたブロックからの返り値によって分類します。ブロックからの返り値をキーとして値を対応付けたMultimapを返します。

Classify items in self by returned value from block. Returns a Multimap whose values are associated with keys. Keys’ are defined by returned value from given block.



812
813
814
815
816
817
818
# File 'lib/multiset.rb', line 812

def group_by
  ret = Multimap.new
  @entries.each_pair do |item, count|
    ret[yield(item)].add(item, count)
  end
  ret
end

#group_by_withObject Also known as: classify_with

Multiset#group_byと同様ですが、ブロックには要素とその個数の組が与えられます。

Same as Multiset#group_by, but the pairs of (non-duplicate) items and their counts are given to block.



824
825
826
827
828
829
830
# File 'lib/multiset.rb', line 824

def group_by_with
  ret = Multimap.new
  @entries.each_pair do |item, count|
    ret[yield(item, count)].add(item, count)
  end
  ret
end

#hashObject

:nodoc:



186
187
188
189
190
191
192
# File 'lib/multiset.rb', line 186

def hash # :nodoc:
  val = 0
  @entries.each_pair do |item, count|
    val += item.hash * count
  end
  val
end

#include?(item) ⇒ Boolean Also known as: member?

itemself中に含まれているかを返します。

Returns whether self has item.

Returns:

  • (Boolean)


256
257
258
# File 'lib/multiset.rb', line 256

def include?(item)
  @entries.has_key?(item)
end

#inject_with(init) ⇒ Object

ブロックに「1回前のブロック呼び出しの返り値」「selfの要素」「その個数」の3つ組を順次与え、最後にブロックを呼んだ結果を返します。ただし「1回前のブロック呼び出しの返り値」は、1回目のブロック呼び出しの際については、代わりにinitの値が与えられます。

Enumerable#injectと異なり、initは省略できません。またブロックの代わりにSymbolを与えることもできません。

Three elements are given to the block for each (non-duplicate) items: the last result of the block, the item and its count. As for the first block call, the first argument is init. The result of the last block call is returned.

Different from Enumerable#inject, init cannot be omitted. In addition, Symbol cannot be given instead of a block.



956
957
958
959
960
961
# File 'lib/multiset.rb', line 956

def inject_with(init)
  @entries.each_pair do |item, count|
    init = yield(init, item, count)
  end
  init
end

#inspectObject

:nodoc:



306
307
308
309
310
311
# File 'lib/multiset.rb', line 306

def inspect # :nodoc:
  buf = "#<Multiset:"
  buf += self.to_s(', ')
  buf += '>'
  buf
end

#itemsObject

selfに含まれている要素(重複は除く)からなる配列を返します。

Returns an array with all items in self, without duplication.



239
240
241
# File 'lib/multiset.rb', line 239

def items
  @entries.keys
end

#listing(delim = "\n") ⇒ Object

selfの全要素を(重複を許して)並べた文字列を返します。要素間の区切りはdelimの値を用い、各要素の表示形式は与えられたブロックの返り値(なければObject#inspect)を用います。

Lists all items with duplication in self. Items are deliminated with delim, and items are converted to string in the given block. If block is omitted, Object#inspect is used.



269
270
271
272
273
274
275
276
277
278
279
280
281
# File 'lib/multiset.rb', line 269

def listing(delim = "\n")
  buf = ''
  init = true
  self.each do |item|
    if init
      init = false
    else
      buf += delim
    end
    buf += block_given? ? yield(item).to_s : item.inspect
  end
  buf
end

#mapObject Also known as: collect

selfの各要素(重複なし)をブロックに与え、返り値を集めたものからなる多重集合を生成します。

Gives all items in self (without duplication) to given block, and generates a new multiset whose values are returned value from the block.



634
635
636
637
638
639
640
# File 'lib/multiset.rb', line 634

def map # :yields: item
  ret = Multiset.new
  @entries.each_pair do |item, count|
    ret.add(yield(item), count)
  end
  ret
end

#map!(&block) ⇒ Object Also known as: collect!

Multiset#mapと同様ですが、結果として生成される多重集合でselfが置き換えられます。selfを返します。

Same as Multiset#map, but replaces self by resulting multiset. Returns self.



648
649
650
651
# File 'lib/multiset.rb', line 648

def map!(&block) # :yields: item
  self.replace(self.map(&block))
  self
end

#map_withObject Also known as: collect_with

selfの要素(重複なし)とその個数の組をブロックに与えます。ブロックから2要素の配列を受け取り、前者を要素、後者をその個数とした多重集合を生成します。

Gives all pairs of (non-duplicate) items and their numbers in self to given block. The block must return an array of two items. Generates a new multiset whose values and numbers are the first and second item of returned array, respectively.



662
663
664
665
666
667
668
669
# File 'lib/multiset.rb', line 662

def map_with
  ret = Multiset.new
  @entries.each_pair do |item, count|
    val = yield(item, count)
    ret.add(val[0], val[1])
  end
  ret
end

#map_with!Object Also known as: collect_with!

Multiset#map_withと同様ですが、結果として生成される多重集合でselfが置き換えられます。selfを返します。

Same as Multiset#map_with, but replaces self by resulting multiset. Returns self.



677
678
679
680
681
682
683
684
# File 'lib/multiset.rb', line 677

def map_with!
  self.to_hash.each_pair do |item, count|
    self.delete(item, count)
    val = yield(item, count)
    self.add(val[0], val[1])
  end
  self
end

#max(&block) ⇒ Object

最大の要素を返します。要素が存在しない場合はnilを返します。ブロックが与えられた場合は、要素間の大小判定を、ブロックに2つの要素を与えることで行います。

Returns the largest item, or nil if no item is stored in self. If a block is given, their order is judged by giving two items to the block.



969
970
971
# File 'lib/multiset.rb', line 969

def max(&block) # :yields: a, b
  @entries.keys.max(&block)
end

#max_by(&block) ⇒ Object

ブロックの値を評価した結果が最大になるような要素を返します。要素が存在しない場合はnilを返します。

Returns the largest item, or nil if no item is stored in self.



996
997
998
# File 'lib/multiset.rb', line 996

def max_by(&block) # :yields: item
  @entries.keys.max_by(&block)
end

#max_by_with(&block) ⇒ Object

Multiset#max_by と同様ですが、ブロックには要素(重複なし)とその出現数の組が与えられます。

Same as Multiset#min, but pairs of (non-duplicated) items and their counts are given to the block.



1046
1047
1048
1049
# File 'lib/multiset.rb', line 1046

def max_by_with(&block) # :yields: item
  tmp = @entries.each_pair.max_by(&block)
  tmp ? tmp[0] : nil # if @entries is not empty, tmp must be a two-element array
end

#max_withObject

Multiset#max と同様ですが、ブロックには「要素1」「要素1の出現数」「要素2」「要素2の出現数」の4引数が与えられます。

Same as Multiset#max, but four arguments: “item 1”, “number of item 1”, “item 2” and “number of item 2” are given to the block.



1020
1021
1022
1023
# File 'lib/multiset.rb', line 1020

def max_with # :yields: item1, count1, item2, count2
  tmp = @entries.each_pair.max{ |a, b| yield(a[0], a[1], b[0], b[1]) }
  tmp ? tmp[0] : nil
end

#merge(other) ⇒ Object Also known as: +

selfotherの要素を合わせた多重集合を返します。

Returns merged multiset of self and other.



494
495
496
497
498
499
500
# File 'lib/multiset.rb', line 494

def merge(other)
  ret = self.dup
  other.each_pair do |item, count|
    ret.add(item, count)
  end
  ret
end

#merge!(other) ⇒ Object

selfotherの要素を追加します。selfを返します。

Merges other to self. Returns self.



508
509
510
511
512
513
# File 'lib/multiset.rb', line 508

def merge!(other)
  other.each_pair do |item, count|
    self.add(item, count)
  end
  self
end

#min(&block) ⇒ Object

最小の要素を返します。要素が存在しない場合はnilを返します。ブロックが与えられた場合は、要素間の大小判定を、ブロックに2つの要素を与えることで行います。

Returns the smallest item, or nil if no item is stored in self. If a block is given, their order is judged by giving two items to the block.



979
980
981
# File 'lib/multiset.rb', line 979

def min(&block) # :yields: a, b
  @entries.keys.min(&block)
end

#min_by(&block) ⇒ Object

ブロックの値を評価した結果が最小になるような要素を返します。要素が存在しない場合はnilを返します。

Returns the smallest item, or nil if no item is stored in self.



1004
1005
1006
# File 'lib/multiset.rb', line 1004

def min_by(&block) # :yields: item
  @entries.keys.min_by(&block)
end

#min_by_with(&block) ⇒ Object

Multiset#min_by と同様ですが、ブロックには要素(重複なし)とその出現数の組が与えられます。

Same as Multiset#max, but pairs of (non-duplicated) items and their counts are given to the block.



1054
1055
1056
1057
# File 'lib/multiset.rb', line 1054

def min_by_with(&block) # :yields: item
  tmp = @entries.each_pair.min_by(&block)
  tmp ? tmp[0] : nil # if @entries is not empty, tmp must be a two-element array
end

#min_withObject

Multiset#min と同様ですが、ブロックには「要素1」「要素1の出現数」「要素2」「要素2の出現数」の4引数が与えられます。

Same as Multiset#min, but four arguments: “item 1”, “number of item 1”, “item 2” and “number of item 2” are given to the block.



1029
1030
1031
1032
# File 'lib/multiset.rb', line 1029

def min_with # :yields: item1, count1, item2, count2
  tmp = @entries.each_pair.min{ |a, b| yield(a[0], a[1], b[0], b[1]) }
  tmp ? tmp[0] : nil
end

#minmax(&block) ⇒ Object

最小の要素と最大の要素の組を返します。ブロックが与えられた場合は、要素間の大小判定を、ブロックに2つの要素を与えることで行います。

Returns the pair consisting of the smallest and the largest item. If a block is given, their order is judged by giving two items to the block.



988
989
990
# File 'lib/multiset.rb', line 988

def minmax(&block) # :yields: a, b
  @entries.keys.minmax(&block)
end

#minmax_by(&block) ⇒ Object

ブロックの値を評価した結果が最小になる要素と最大になる要素の組を返します。要素が存在しない場合はnilを返します。

Returns the pair consisting of the smallest and the largest item.



1012
1013
1014
# File 'lib/multiset.rb', line 1012

def minmax_by(&block) # :yields: item
  @entries.keys.minmax_by(&block)
end

#minmax_by_with(&block) ⇒ Object

Multiset#minmax_by と同様ですが、ブロックには要素(重複なし)とその出現数の組が与えられます。

Same as Multiset#minmax, but pairs of (non-duplicated) items and their counts are given to the block.



1062
1063
1064
1065
# File 'lib/multiset.rb', line 1062

def minmax_by_with(&block) # :yields: item
  tmp = @entries.each_pair.minmax_by(&block)
  tmp[0] ? [tmp[0][0], tmp[1][0]] : nil
end

#minmax_withObject

Multiset#minmax と同様ですが、ブロックには「要素1」「要素1の出現数」「要素2」「要素2の出現数」の4引数が与えられます。

Same as Multiset#minmax, but four arguments: “item 1”, “number of item 1”, “item 2” and “number of item 2” are given to the block.



1038
1039
1040
1041
# File 'lib/multiset.rb', line 1038

def minmax_with # :yields: item1, count1, item2, count2
  tmp = @entries.each_pair.minmax{ |a, b| yield(a[0], a[1], b[0], b[1]) }
  tmp ? [tmp[0][0], tmp[1][0]] : nil
end

#proper_subset?(other) ⇒ Boolean

selfotherに真に含まれているかどうかを返します。「真に」とは、両者が一致する場合は含めないことを示します。

Returns whether self is a proper subset of other.

Returns:

  • (Boolean)


470
471
472
473
474
475
# File 'lib/multiset.rb', line 470

def proper_subset?(other)
  unless other.instance_of?(Multiset)
    raise ArgumentError, "Argument must be a Multiset"
  end
  self.subset?(other) && self != other
end

#proper_superset?(other) ⇒ Boolean

selfotherを真に含んでいるかどうかを返します。「真に」とは、両者が一致する場合は含めないことを示します。

Returns whether self is a proper superset of other.

Returns:

  • (Boolean)


449
450
451
452
453
454
# File 'lib/multiset.rb', line 449

def proper_superset?(other)
  unless other.instance_of?(Multiset)
    raise ArgumentError, "Argument must be a Multiset"
  end
  self.superset?(other) && self != other
end

#rejectObject

ブロックにselfの要素(重複なし)を順次与え、結果が偽であった要素のみを集めたMultisetを返します。

Gives all items in self (without duplication) to given block, and returns a multiset collecting the items whose results in the block are false.



743
744
745
746
747
748
749
# File 'lib/multiset.rb', line 743

def reject
  ret = Multiset.new
  @entries.each_pair do |item, count|
    ret.renew_count(item, count) unless yield(item)
  end
  ret
end

#reject!Object

Multiset#delete_ifと同じですが、要素が1つも削除されなければnilを返します。

Same as Multiset#delete_if, but returns nil if no item is deleted.



767
768
769
770
771
772
773
774
775
776
# File 'lib/multiset.rb', line 767

def reject!
  ret = nil
  @entries.each_pair do |item, count|
    if yield(item)
      self.delete_all(item)
      ret = self
    end
  end
  ret
end

#reject_withObject

ブロックにselfの要素(重複なし)と個数の組を順次与え、結果が偽であった要素のみを集めたMultisetを返します。

Gives all pairs of (non-duplicate) items and counts in self to given block, and returns a multiset collecting the items whose results in the block are false.



756
757
758
759
760
761
762
# File 'lib/multiset.rb', line 756

def reject_with
  ret = Multiset.new
  @entries.each_pair do |item, count|
    ret.renew_count(item, count) unless yield(item, count)
  end
  ret
end

#renew_count(item, number) ⇒ Object

selfに含まれるitemの個数をnumber個にします。numberが負の数であった場合は、number = 0とみなします。成功した場合はselfを、失敗した場合はnilを返します。

Sets number of item to number in self. If number is negative, treats as number = 0. Returns self if succeeded, nil otherwise.



363
364
365
366
367
368
369
370
371
372
# File 'lib/multiset.rb', line 363

def renew_count(item, number)
  return nil if number == nil
  n = number.to_i
  if n > 0
    @entries[item] = n
  else
    @entries.delete(item)
  end
  self
end

#replace(other) ⇒ Object

selfの内容をotherのものに置き換えます。selfを返します。

Replaces self by other. Returns self.



213
214
215
216
217
218
219
# File 'lib/multiset.rb', line 213

def replace(other)
  @entries.clear
  other.each_pair do |item, count|
    self.renew_count(item, count)
  end
  self
end

#sampleObject Also known as: rand

selfの要素を無作為に1つ選んで返します。すべての要素は等確率で選ばれます。空のmultisetに対して呼び出した場合はnilを返します。

Returns one item in self randomly. All items are selected with the same probability. Returns nil in case the multiset is empty.



694
695
696
697
698
699
700
701
# File 'lib/multiset.rb', line 694

def sample
  return nil if empty?
  pos = Kernel.rand(self.size)
  @entries.each_pair do |item, count|
    pos -= count
    return item if pos < 0
  end
end

#sizeObject Also known as: length

selfに含まれている要素数を返します。

Returns number of all items in self.



224
225
226
# File 'lib/multiset.rb', line 224

def size
  @entries.inject(0){ |sum, item| sum += item[1] }
end

#sort(&block) ⇒ Object

selfの要素を並び替えた配列を生成します。

Generates an array by sorting the items in self.



1070
1071
1072
1073
1074
1075
1076
# File 'lib/multiset.rb', line 1070

def sort(&block) # :yields: a, b
  ret = []
  @entries.keys.sort(&block).each do |item|
    ret.fill(item, ret.length, @entries[item])
  end
  ret
end

#sort_by(&block) ⇒ Object

Multiset#sortと同様ですが、ブロックには1つの要素が与えられ、その値が小さいものから順に並びます。

Same as Multiset#sort, but only one item is given to the block.



1081
1082
1083
1084
1085
1086
1087
# File 'lib/multiset.rb', line 1081

def sort_by(&block) # :yields: item
  ret = []
  @entries.keys.sort_by(&block).each do |item|
    ret.fill(item, ret.length, @entries[item])
  end
  ret
end

#sort_by_withObject

Multiset#sort_by と同様ですが、ブロックには要素(重複なし)とその出現数の組が与えられます。

Same as Multiset#sort_by, but pairs of (non-duplicated) items and their counts are given to the block.



1104
1105
1106
1107
1108
1109
1110
# File 'lib/multiset.rb', line 1104

def sort_by_with # :yields: item1, count1, item2, count2
  ret = []
  @entries.each_pair.sort_by{ |a| yield(*a) }.each do |item_count|
    ret.fill(item_count[0], ret.length, item_count[1])
  end
  ret
end

#sort_withObject

Multiset#sort と同様ですが、ブロックには「要素1」「要素1の出現数」「要素2」「要素2の出現数」の4引数が与えられます。

Same as Multiset#sort, but four arguments: “item 1”, “number of item 1”, “item 2” and “number of item 2” are given to the block.



1093
1094
1095
1096
1097
1098
1099
# File 'lib/multiset.rb', line 1093

def sort_with # :yields: item1, count1, item2, count2
  ret = []
  @entries.each_pair.sort{ |a, b| yield(a[0], a[1], b[0], b[1]) }.each do |item_count|
    ret.fill(item_count[0], ret.length, item_count[1])
  end
  ret
end

#subset?(other) ⇒ Boolean

selfotherに含まれているかどうかを返します。

Returns whether self is a subset of other.

Returns:

  • (Boolean)


459
460
461
462
463
464
# File 'lib/multiset.rb', line 459

def subset?(other)
  unless other.instance_of?(Multiset)
    raise ArgumentError, "Argument must be a Multiset"
  end
  compare_set_with(other){ |s, o| s <= o }
end

#subtract(other) ⇒ Object Also known as: -

selfからotherの要素を取り除いた多重集合を返します。

Returns multiset such that items in other are removed from self.



518
519
520
521
522
523
524
# File 'lib/multiset.rb', line 518

def subtract(other)
  ret = self.dup
  other.each_pair do |item, count|
    ret.delete(item, count)
  end
  ret
end

#subtract!(other) ⇒ Object

selfからotherの要素を削除します。selfを返します。

Removes items in other from self. Returns self.



532
533
534
535
536
537
# File 'lib/multiset.rb', line 532

def subtract!(other)
  other.each_pair do |item, count|
    self.delete(item, count)
  end
  self
end

#superset?(other) ⇒ Boolean

selfotherを含んでいるかどうかを返します。

Returns whether self is a superset of other.

Returns:

  • (Boolean)


438
439
440
441
442
443
# File 'lib/multiset.rb', line 438

def superset?(other)
  unless other.instance_of?(Multiset)
    raise ArgumentError, "Argument must be a Multiset"
  end
  compare_set_with(other){ |s, o| s >= o }
end

#to_aObject

selfを配列に変換して返します。

Converts self to an array.



178
179
180
181
182
183
184
# File 'lib/multiset.rb', line 178

def to_a
  ret = []
  @entries.each_pair do |item, count|
    ret.concat Array.new(count, item)
  end
  ret
end

#to_hashObject

selfHashに変換して返します。生成されるハッシュの構造については、Hash#to_multisetをご覧下さい。

Converts self to a Hash. See Hash#to_multiset about format of generated hash.



146
147
148
# File 'lib/multiset.rb', line 146

def to_hash
  @entries.dup
end

#to_s(delim = "\n") ⇒ Object

selfの要素と要素数の組を並べた文字列を返します。要素間の区切りはdelimの値を用い、各要素の表示形式は与えられたブロックの返り値(なければObject#inspect)を用います。

Lists all items without duplication and its number in self. Items are deliminated with delim, and items are converted to string in the given block. If block is omitted, Object#inspect is used.



291
292
293
294
295
296
297
298
299
300
301
302
303
304
# File 'lib/multiset.rb', line 291

def to_s(delim = "\n")
  buf = ''
  init = true
  @entries.each_pair do |item, count|
    if init
      init = false
    else
      buf += delim
    end
    item_tmp = block_given? ? yield(item) : item.inspect
    buf += "\##{count} #{item_tmp}"
  end
  buf
end

#to_setObject

selfを通常の集合(Ruby標準添付のSet)に変換したものを返します。

このメソッドを呼び出すと、require "set"が行われます。

なおSetをMultisetに変換するには、Multiset.new(instance_of_set)で可能です。

Converts self to ordinary set (The Set class attached to Ruby by default).

require "set" is performed when this method is called.

To convert Set to Multiset, use Multiset.new(instance_of_set).



170
171
172
173
# File 'lib/multiset.rb', line 170

def to_set
  require "set"
  Set.new(@entries.keys)
end

#|(other) ⇒ Object

selfotherの和集合からなる多重集合を返します。

Returns union of self and other.



553
554
555
556
557
558
559
# File 'lib/multiset.rb', line 553

def |(other)
  ret = self.dup
  other.each_pair do |item, count|
    ret.renew_count(item, [self.count(item), count].max)
  end
  ret
end