Module: Mapping

Defined in:
lib/maset/mapping.rb

Overview

要素同士の対応を扱うモジュール。

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.corresponding?(left, right) ⇒ Boolean

map? よりもゆるく、多対多でも等しい要素の数が同じであれば true. e.g., a0 = [‘b’, ‘c’, ‘a’, ‘a’] a1 = [‘a’, ‘a’, ‘b’, ‘c’] のとき、Mapping::corresponding?( a0, a1 ) #=> true

Returns:

  • (Boolean)


65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# File 'lib/maset/mapping.rb', line 65

def self.corresponding?( left, right )
	return false if ( left.size != right.size )

	l_indices = Mapping::map( left , right ){ |a, b| yield( a, b ) }
	r_indices = Mapping::map( right, left  ){ |a, b| yield( a, b ) }
	#p r_indices; exit
	l_indices.size.times do |i|
		results = []
		return false if l_indices[i].empty? #対応が空のものがあれば false 確定。
		l_indices[i].each do |x| #左の i 番要素は 右へのインデックスの配列なので、それを each
			return false if l_indices[i].size != r_indices[x].size #対応の数が異なれば false。この条件には 右側が空であることも含まれる。
			r_indices[x].each do |y| #対応する右の要素は、左へのインデックスの配列なので、それを each
				results << l_indices[y] #さらに左の要素で、反射して対応する全てが得られる。
			end
		end
		#p results.flatten.uniq
		#p l_indices[i]
		#全部 [] のときも true になっちまう。
		#対応がない場合も考えないとなー。
		#どれか、どちらかが一つでも空対応のときは false でいいか。
		return false if ( results.flatten.uniq != l_indices[i] )
	end
	return true

	#l_hash = Hash.new
	#r_hash = Hash.new
	#left.uniq.each do |i|
	#	l_hash[ i ] = left .select{ |j| yield( i, j ) }.size
	#	r_hash[ i ] = right.select{ |j| yield( i, j ) }.size
	#end
	#p l_hash, r_hash
	#return l_hash == r_hash
end

.map(left, right) ⇒ Object

左のコンテナに注目し、右のコンテナにある条件を満たすインデックス全てを 入れた配列を返す。 等価なものを探すことなどに使える。 右のコンテナに等価なものがなければ空配列が入る。 e.g., left = [‘a’, ‘b’, ‘c’, ‘d’]

right = ['b', 'c', 'a', 'a']
のとき、
self.left_to_right(left, right) #=> [ [2, 3], [0], [1], [] ]

必ずブロックが渡されることを前提とする。 ブロックをたとえば { |i, j| i == j } とすれば、 left, right それぞれに由来する要素 i, j を == 演算で等価判定していることになる。 ブロックに渡すのは等価判定でなくても構わない。



34
35
36
37
38
39
40
41
# File 'lib/maset/mapping.rb', line 34

def self.map( left, right )
	size = left.size
	results = Array.new( size, [] )
	size.times do |n|
		results[n] = right.find_all_indices{ |i| yield( i, left[n] )  }
	end
	results
end

.map?(left, right) ⇒ Boolean

2つのコンテナが一対一対応していれば true、そうでなければ false 自分と自分でも多対多の対応になる可能性があり、その場合は false

Returns:

  • (Boolean)


45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/maset/mapping.rb', line 45

def self.map?(left, right)
	return true  if ((left.size == 0 ) && (right.size == 0))
	return false if ((left.size == 0 ) || (right.size == 0)) #どちらかが 0 でどちらかが非0

	l2r = self.map(left, right){ |i, j| yield( i, j ) }
	r2l = self.map(right, left){ |i, j| yield( i, j ) }
	result = true
	result = false if ( l2r.max_by{|i| i.size }.size != 1 )
	result = false if ( l2r.min_by{|i| i.size }.size != 1 )
	result = false if ( r2l.max_by{|i| i.size }.size != 1 )
	result = false if ( r2l.min_by{|i| i.size }.size != 1 )
	#max_by, min_by は要素を返すため、それに操作を改めて加えてサイズを出す。
	result
end

Instance Method Details

#corresponding?(other) ⇒ Boolean

クラスに include されたときに Mapping::corresponding? をクラスメソッドとして使えるようにしたもの。

Returns:

  • (Boolean)


102
103
104
# File 'lib/maset/mapping.rb', line 102

def corresponding?( other )
	Mapping::corresponding?( self, other ){ |i, j| yield( i, j ) }
end

#map?(other) ⇒ Boolean

引数のコンテナと一対一で対応すれば true, そうでなければ false。 自分と比較しても多対多の対応になる可能性があり、その場合は false

Returns:

  • (Boolean)


118
119
120
# File 'lib/maset/mapping.rb', line 118

def map?(other)
	Mapping::map?(self, other){ |i, j| yield( i, j ) }
end

#map_from(other) ⇒ Object

引数のコンテナから自分数への写像と考えたときの、対応するインデックスを配列して返す。



112
113
114
# File 'lib/maset/mapping.rb', line 112

def map_from(other)
	Mapping::map(other, self){ |i, j| yield( i, j ) }
end

#map_to(other) ⇒ Object

自分から引数のコンテナへの写像と考えたときの、対応するインデックスを配列して返す。



107
108
109
# File 'lib/maset/mapping.rb', line 107

def map_to(other)
	Mapping::map(self, other){ |i, j| yield( i, j ) }
end