メソッド set.union
メソッド set.union のヘルプ情報を確認します。
>>> help(set.union)
Help on method_descriptor:
union(...)
Return the union of two sets as a new set.
(i.e. all elements that are in either set.)
これを見て、2つの集合をもとに、新たな集合(和集合)が得られるのが分かります。実際に、その動作を確認してみましょう。
>>> s1 = set("AB")
>>> s2 = set("BC")
>>> s1.union(s2)
set(['A', 'C', 'B'])
2つの集合 s1/s2 の「どちらかに」含まれる要素を列挙した、集合が得られます。
メソッド set.difference
メソッド set.difference のヘルプ情報を確認します。
>>> help(set.difference)
Help on method_descriptor:
difference(...)
Return the difference of two sets as a new set.
(i.e. all elements that are in this set but not the other.)
これを見て、2つの集合をもとに、新たな集合(差集合)が得られるのが分かります。実際に、その動作を確認してみましょう。
>>> s1 = set("AB")
>>> s2 = set("BC")
>>> s1.difference(s2)
set(['A'])
集合 s1 から集合 s2 の要素を除くと、要素 'A' だけが残ります。
>>> s2.difference(s1)
set(['C'])
集合 s2 から集合 s1 の要素を除くと、要素 'C' だけが残ります。
ソースコード:SetCollection.Union(object)
(メソッド set.union に相当する)メソッド Union の定義を含む、ソースコードの断片を次に示します。他のメソッド intersection/difference/symmetric_difference についても、同様です。
# IronPython-1.1.2/Src/IronPython/Runtime/Set.cs
public class SetCollection : ISet ...
#region NonOperator Operations
[PythonName("union")]
public object Union(object s) {
return SetHelpers.Union(this, s);
}
[PythonName("intersection")]
public object Intersection(object s) {
return SetHelpers.Intersection(this, s);
}
[PythonName("difference")]
public object Difference(object s) {
return SetHelpers.Difference(this, s);
}
[PythonName("symmetric_difference")]
public object SymmetricDifference(object s) {
return SetHelpers.SymmetricDifference(this, s);
}
public class FrozenSetCollection : ISet ...
#region NonOperator Operations
...
メソッド Union では、メソッド SetHelpers.Union の実引数に、this を指定しています。これは、静的クラス SetHelpers で共有する操作を実現しているので、それに自身 this の処理を委ねるためです。このとき(SetCollection のインスタンス)this は、インターフェース ISet の規定に従うものとします。他方のクラス FrozenSetCollection についても、同様です。
ソースコード:ISet.PrivFreeze()
メソッド ISet.PrivFreeze の定義を含む、ソースコードの断片を次に示します。
internal interface ISet : IEnumerable {
void PrivFreeze();
インターフェース ISet を実現するクラス(SetCollection/FrozenSetCollection)では、メソッド PrivFreeze を実現する必要があります。
public class SetCollection : ISet ...
void ISet.PrivFreeze() {
// nop for non-frozen sets.
}
クラス SetCollection では、なにもする必要がないので、メソッドの本体は空です。
public class FrozenSetCollection : ISet ...
int hashCode;
void ISet.PrivFreeze() {
CalculateHashCode();
}
void CalculateHashCode() {
hashCode = 6551;
...
}
クラス FrozenSetCollection では、ハッシュコードを再計算する必要があります。(補助関数として)メソッド CalculateHashCode では、インスタンス属性 hashCode の値を再設定します。その詳細は、ここでは割愛します。
■
# IronPython-1.1.2/Src/IronPython/Runtime/Set.cs
static class SetHelpers {
...
public static ISet Union(ISet x, object y) {
ISet set = SetHelpers.MakeSet(x, x);
IEnumerator ie = Ops.GetEnumerator(y);
while (ie.MoveNext()) {
set.PrivAdd(ie.Current);
}
set.PrivFreeze();
return set;
}
public static ISet Intersection(ISet x, object y) {
ISet res = SetHelpers.MakeSet(x);
IEnumerator ie = Ops.GetEnumerator(y);
while (ie.MoveNext()) {
if (x.Contains(ie.Current) == Ops.TRUE)
res.PrivAdd(ie.Current);
}
res.PrivFreeze();
return res;
}
public static ISet Difference(ISet x, object y) {
ISet res = SetHelpers.MakeSet(x, x) as ISet;
Debug.Assert(res != null);
IEnumerator ie = Ops.GetEnumerator(y);
while (ie.MoveNext()) {
if (res.Contains(ie.Current) == Ops.TRUE) {
res.PrivRemove(ie.Current);
}
}
res.PrivFreeze();
return res;
}
public static ISet SymmetricDifference(ISet x, object y) {
SetCollection otherSet = new SetCollection(Ops.GetEnumerator(y)); //make a set to deal w/ dups in the enumerator
ISet res = SetHelpers.MakeSet(x, x) as ISet;
Debug.Assert(res != null);
foreach (object o in otherSet) {
if (res.Contains(o) == Ops.TRUE) {
res.PrivRemove(o);
} else {
res.PrivAdd(o);
}
}
res.PrivFreeze();
return res;
}
- -
メソッド set.intersection
メソッド set.intersection のヘルプ情報を確認します。
>>> help(set.intersection)
Help on method_descriptor:
intersection(...)
Return the intersection of two sets as a new set.
(i.e. all elements that are in both sets.)
これを見て、2つの集合をもとに、新たな集合(積集合)が得られるのが分かります。実際に、その動作を確認してみましょう。
>>> s1 = set("AB")
>>> s2 = set("BC")
>>> s1.intersection(s2)
set(['B'])
2つの集合 s1/s2 の「どちらにも」含まれる要素を列挙した、集合が得られます。
メソッド set.symmetric_difference
メソッド set.symmetric_difference のヘルプ情報を確認します。
>>> help(set.symmetric_difference)
Help on method_descriptor:
symmetric_difference(...)
Return the symmetric difference of two sets as a new set.
(i.e. all elements that are in exactly one of the sets.)
これを見て、2つの集合をもとに、新たな集合(対称差集合)が得られるのが分かります。実際に、その動作を確認してみましょう。
>>> s1 = set("AB")
>>> s2 = set("BC")
>>> s1.symmetric_difference(s2)
set(['A', 'C'])
2つの集合 s1/s2 の「どちらか一方にだけ」含まれる要素を列挙した、集合が得られます。
ソースコード:SetHelpers.MakeSet(object, ISet)
静的メソッド MakeSet の定義を含む、ソースコードの断片を次に示します。
public static ISet MakeSet(object setObj, ISet set) {
Type t = setObj.GetType();
if (t == typeof(SetCollection)) {
return new SetCollection(set);
} else if (t == typeof(FrozenSetCollection)) {
return new FrozenSetCollection(set);
} else {
// subclass
UserType ut = Ops.GetDynamicType(setObj) as UserType;
Debug.Assert(ut != null);
ISet res = Ops.Call(ut) as ISet;
Debug.Assert(res != null);
res.SetData(set);
return res;
}
}
与えられた引数 setObj の型に合わせて、引数 set と同じ要素を列挙したインスタンス(SetCollection/FrozenSetCollection)を生成して、それをリターン値とします。メソッド本体を見ると、次に示す典型的な C# のイディオムが記述してあります。
Type t = obj.GetType();
if (t == typeof(A)) {
return new A(...);
} else if (t == typeof(B)) {
return new B(...);
} else {
... // 利用者が定義した型
}
与えられた obj の型に合わせて、適切なインスタンスを生成します。
《参照》メソッド @GetType の詳細は、http://msdn.microsoft.com/en-us/library/system.collections.ienumerator_members.aspx http://msdn.microsoft.com/en-us/library/system.collections.ienumerator_members.aspxを参照してください。□