說明
集合 (Set
) 是非線性的單一元素的集合,實作數學上的集合論 (set theory)。在 Perl 5,通常是用雜湊模擬集合,Perl 6 則內建集合容器。Bag
和 Set
相似,但會計算該元素出現的次數;Mix
和 Bag
類似,但允許以非整數來計數;除了用來計數外,Bag
和 Mix
和 Set
相當類似。
建立集合
建立串列後呼叫 Set
方法即可將其轉為集合。如下例:
my $set = (2, 1, 2, 4, 3, 4, 3, 3, 2, 1, 5, 1).Set;
$set.elems == 5 or die "Wrong element count";
但是 Set
建立後即不可變動,如果之後要變更其元素,需改用 SetHash
,實例如下:
my $set = (2, 1, 2, 4, 3, 4, 3, 3, 2, 1, 5, 1).SetHash;
$set.elems == 5 or die "Wrong element count";
加入及移除元素
加入元素的方法類似於雜湊,將鍵設為 True
即可;移除時則將鍵設為 False
。
my $set = (1, 2, 3).SetHash;
$set.elems == 3 or die "Wrong element count";
# Add a new element.
$set{4} = True;
$set.elems == 4 or die "Wrong element count";
# Add a duplicated element, no effect.
$set{3} = True;
$set.elems == 4 or die "Wrong element count";
# Remove an element.
$set{1} = False;
$set.elems == 3 or die "Wrong element count";
# Remove a non-existing element, no effect.
$set{1} = False;
$set.elems == 3 or die "Wrong element count";
檢查元素存在性
使用 (cont)
可檢查某集合是否包含某元素,如下例:
my $set= (1, 2, 3, 4, 5).Set;
$set (cont) 1 or die "Wrong status";
($set (cont) 10) == False or die "Wrong status";
也可以使用 (elem)
檢查某元素是否屬於某集合,如下例:
my $set= (1, 2, 3, 4, 5).Set;
1 (elem) $set or die "Wrong status";
(10 (elem) $set) == False or die "Wrong status";
基本上,兩者是同義的,使用自己習慣的方式即可。
集合運算
Perl 6 集合包含一些常見的集合運算,像是聯集 (union)、交集 (intersection)、差集 (difference) 等。實例如下:
my $a = (1, 2, 3).Set;
my $b = (2, 4).Set;
# Union.
$a (|) $b ~~ (1, 2, 3, 4).Set or die "Wrong status";
# Intersection.
$a (&) $b ~~ (2).Set or die "Wrong status";
# Difference.
$a (-) $b ~~ (1, 3).Set or die "Wrong status";
# Symmetric difference.
$a (^) $b ~~ (1, 3, 4).Set or die "Wrong status";
my $c = (2, 3).Set;
# Superset.
$a (>=) $c or die "Wrong status";
# Strict superset.
$a (>) $c or die "Wrong status";
# Subset.
$c (<) $a or die "Wrong status";
# Strict subset.
$c (<=) $a or die "Wrong status";
建立 Bag
對串列呼叫 Bag
方法即可建立 Bag,如下例:
my $bag = (1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 5, 5).Bag;
$bag.elems == 5 or die "Wrong element count";
$bag (cont) 1 or die "Wrong status";
如果建立 Bag 後,需更動其內容,改用 BagHash
即可。
取樣本
由於 Bag 有權重,可設置權重後,對其取樣,如下例:
my $bag = (1 => 9, 2 => 5, 3 => 3, 4 => 2, 5 => 1).Bag;
loop (my $i = 0; $i < 10; $i++) {
$bag.roll(5).sort.say;
}
觀察本程式,可發現每次取像的結果都不同,在其中,1 出現的機率最高。
建立 Mix
由於 Mix
的權重是非整數,較常用的方式是直接對其設權重,如下例:
my $mix = (1 => 0.8, 2 => 0.1, 3 => 0.05, 4 => 0.02, 5 => 0.01).Mix;
loop (my $i = 0; $i < 10; $i++) {
$mix.roll(10).sort.say;
}
如果建立 Mix
後,需更動其內容,改用 MixHash
即可。基本上,Mix
的用法和 Bag
差不多。