class BagHash does Baggy { }

BagHash 是一个可变包/多重集,表示一个特定顺序中不同项的集合,每个项都分配了一个整数权重,表示该元素的副本数被认为“在包中”。如果您不需要 BagHash 提供的可变性,请考虑使用不可变Bag 类型。

项可以是任何类型的明确对象,而不仅仅是 Str。例如,您可以在 BagHash 中存储 Sub,并且您将存储实际的 Sub,而不是与 Sub 同名的字符串。在 BagHash 中,使用 === 运算符比较为正的项被视为同一元素,其权重为有多少个。或者,您可以使用 kxxv 方法轻松地获取展开的项列表(不带顺序)

my $breakfast = <spam eggs spam spam bacon spam>.BagHash;
 
say $breakfast.elems;      # OUTPUT: «3␤» 
say $breakfast.keys.sort;  # OUTPUT: «bacon eggs spam␤» 
 
say $breakfast.total;      # OUTPUT: «6␤» 
say $breakfast.kxxv.sort;  # OUTPUT: «bacon eggs spam spam spam spam␤» 

BagHash 可以使用 { } 后缀运算符< > 后缀运算符(用于字符串文字键)作为对象哈希进行处理,该运算符返回包元素的相应整数权重,对于不是包元素的键返回 0。这些运算符也可用于修改权重(请参阅下面的 更新 BagHash 对象)。

my $breakfast = <spam eggs spam spam bacon spam>.BagHash;
say $breakfast<bacon>;     # OUTPUT: «1␤» 
say $breakfast<spam>;      # OUTPUT: «4␤» 
say $breakfast<sausage>;   # OUTPUT: «0␤» 
 
$breakfast<sausage> = 2;
$breakfast<bacon>--;
say $breakfast.kxxv.sort;  # OUTPUT: «eggs sausage sausage spam spam spam spam␤» 

创建 BagHash 对象§

可以使用 BagHash.new 编写 BagHash。任何位置参数,无论其类型如何,都成为包的元素

my $n = BagHash.new: "a""b""c""c";
say $n.raku;             # OUTPUT: «("b"=>1,"a"=>1,"c"=>2).BagHash␤» 
say $n.keys.raku;        # OUTPUT: «("b", "a", "c").Seq␤» 
say $n.values.raku;      # OUTPUT: «(1, 1, 2).Seq␤»

此外,BagHash.new-from-pairs 可以使用项及其出现次数创建 BagHash

my $n = BagHash.new-from-pairs: "a" => 0"b" => 1"c" => 2"c" => 2;
say $n.raku;             # OUTPUT: «("b"=>1,"c"=>4).BagHash␤» 
say $n.keys.raku;        # OUTPUT: «("b", "c").Seq␤» 
say $n.values.raku;      # OUTPUT: «(1, 4).Seq␤»

或者,可以在现有对象上调用 .BagHash 强制转换器(或其函数形式 BagHash())以将其强制转换为 BagHash。其语义取决于对象的类型和内容。通常,它在列表上下文中评估对象,并创建一个包,其中结果项作为元素,但对于类似哈希的对象或 Pair 项,只有键成为包的元素,而(累积)值成为关联的整数权重

my $m = ("a""b""c""c").BagHash;
my $n = ("a" => 0"b" => 1"c" => 2"c" => 2).BagHash;
say $m.raku;             # OUTPUT: «("b"=>1,"a"=>1,"c"=>2).BagHash␤» 
say $n.raku;             # OUTPUT: «("b"=>1,"c"=>4).BagHash␤»

您还可以使用 is 特性创建伪装成哈希的 BagHash

my %bh is BagHash = <a b b c c c>;
say %bh<b>;  # OUTPUT: «2␤» 
say %bh<d>;  # OUTPUT: «0␤»

从 6.d(2019.03 及更高版本)开始,还可以指定您希望在 BagHash 中允许的值类型。这可以在调用 .new 时完成

# only allow strings 
my $n = BagHash[Str].new: <a b b c c c>;

或使用伪装语法

# only allow strings 
my %bh is BagHash[Str= <a b b c c c>;
say %bh<b>;  # OUTPUT: «2␤» 
say %bh<d>;  # OUTPUT: «0␤» 
 
# only allow whole numbers 
my %bh is BagHash[Int= <a b b c c c>;
# Type check failed in binding; expected Int but got Str ("a")

更新 BagHash 对象§

创建 BagHash 后,您可以通过两种方式更新其值。首先,您可以使用 addremove 方法

my $n = BagHash.new: "a""b""c""c";
say $n.raku;             # OUTPUT: «("b"=>1,"a"=>1,"c"=>2).BagHash␤» 
$n.add('c');
say $n.raku;             # OUTPUT: «("b"=>1,"c"=>3,"a"=>1).BagHash␤» 
$n.remove(('b''a'),);
say $n.raku;             # OUTPUT: «("c"=>3).BagHash␤» 
$n.remove('c');
say $n.raku;             # OUTPUT: «("c"=>2).BagHash␤»

请注意,如最后一个示例所示,remove 方法从 BagHash 中删除一个单个值;它不会完全从 BagHash 中删除该键。

或者,你可以使用赋值(包括使用 自动增量运算符,如 ++--)来修改 BagHash 的内容。

my $n = BagHash.new: "a""b""c""c";
say $n.raku;             # OUTPUT: «("b"=>1,"a"=>1,"c"=>2).BagHash␤» 
$n<c>++;
say $n.raku;             # OUTPUT: «("b"=>1,"c"=>3,"a"=>1).BagHash␤» 
$n<b> -= 1;
say $n.raku;             # OUTPUT: «("a"=>1,"c"=>3).BagHash␤» 
$n{'a'} = 0;
say $n.raku;             # OUTPUT: «("c"=>3).BagHash␤»

使用任一语法,如果你将某个项的值设置为零或小于零,该项将从 BagHash 中移除。

运算符§

请参阅 具有集合语义的运算符 以获取适用于 BagHash 等类型的“集合运算符”的完整列表。

示例

my ($a$b= BagHash.new(224), BagHash.new(2334);
 
say $a (<) $b;   # OUTPUT: «False␤» 
say $a (<=) $b;  # OUTPUT: «False␤» 
say $a (^) $b;   # OUTPUT: «BagHash(3(2) 2)␤» 
say $a (+) $b;   # OUTPUT: «BagHash(2(3) 4(2) 3(2))␤» 
 
# Unicode versions: 
say $a  $b;  # OUTPUT: «False␤» 
say $a  $b;  # OUTPUT: «False␤» 
say $a  $b;  # OUTPUT: «BagHash(3(2) 2)␤» 
say $a  $b;  # OUTPUT: «BagHash(2(3) 4(2) 3(2))␤» 

关于 reverse 和排序的说明。§

BagHash 从 Any 继承了 reverse,但是,Bag 没有固有的顺序,你不应该相信它会返回一致的输出。

如果你对 BagHash 进行排序,结果是一个对列表,此时 reverse 非常有意义

my $a = BagHash.new(221834);
say $a;  # OUTPUT: «BagHash(18 2(2) 3 4)␤» 
 
say $a.sort;  # OUTPUT: «(2 => 2 3 => 1 4 => 1 18 => 1)␤» 
say $a.sort.reverse;  # OUTPUT: «(18 => 1 4 => 1 3 => 1 2 => 2)␤» 

方法 add§

method add(BagHash: \to-add*%_ --> Nil)

to-add 是单个项时,add 将其插入到 BagHash 中,或者如果它已经存在,则将其权重增加 1。当 to-addListArraySeq 或任何其他 does Iterator 角色的类型时,addIterator 的每个元素插入到 SetHash 中或将每个元素的权重增加 1。

注意:在版本 2020.02 中添加。

方法 remove§

method remove(BagHash: \to-remove*%_ --> Nil)

to-remove 是单个项时,remove 将该项的权重减少 1。如果这导致该项的权重为 0,则会从 BagHash 中移除该项。如果该项不存在于 BagHash 中,则 remove 不起作用。当 to-removeListArraySeq 或任何其他 does Iterator 角色的类型时,remove 将每个元素的权重减少 1,并移除权重为 0 的任何项。

注意:在版本 2020.02 中添加。

另请参阅§

集合、包和混合

类型图§

BagHash 的类型关系
raku-type-graph BagHash BagHash Any Any BagHash->Any Baggy Baggy BagHash->Baggy Mu Mu Any->Mu Associative Associative QuantHash QuantHash QuantHash->Associative Baggy->QuantHash

展开上面的图表