我将如何使用 Set 或 Setty 来存储唯一数组?
How would I go about using Set or Setty to store unique arrays?
我有兴趣使用 Set
来保存数组,如下所示:
my @v1 = 1, 2, 3;
my @v2 = 1, 2, 3;
my $set Set.new(@v1, @v2);
如果 Set
能够识别出这两个数组是相同的,正如使用 ~~
运算符所观察到的那样,但 Set
使用 ===
用于比较大多数对象的运算符。
# desired outcome: set([1 2 3])
# actual outcome: set([1 2 3], [1 2 3])
我 可以 在将数组添加到 Set
之前序列化数组,使用奇妙的 Set
魔法,然后反序列化。这似乎很尴尬。
我可以制作一个Setty
class,使用~~
作为比较器。这似乎是一个很好的学习,但也许是错误的。
是否有更惯用的方法来做到这一点?
这两个数组不被认为是相同的,因为它们不是值类型:即,它们在添加到集合后可以更改:
my @a = 1,2,3;
my @b = 1,2,3;
my $s = Set.new(@a,@b);
dd $s; # Set $s = set([1, 2, 3],[1, 2, 3])
@a.push(4);
dd $s; # Set $s = set([1, 2, 3, 4],[1, 2, 3])
Perl 6 中的对象标识由 .WHICH
方法确定。对于值类型,此 returns 值的唯一表示。对于像 Array
s 这样的引用类型,它 returns 根据类型及其对象 ID 唯一标识对象的东西。
目前,身份是使用 ObjAt
class 实现的,但功能仍有一些变化。但是,只要 .WHICH
方法 returns 唯一描述了 你 认为识别你的对象的东西,你应该能够创建你自己的 .WHICH
执行。例如:
role frozen {
method WHICH() {
ObjAt.new(self.join("[=11=]")) # something not occurring in values
}
}
my @a = 1,2,3;
my @b = 1,2,3;
my $s = Set.new(@a but frozen,@b but frozen);
dd $s; # Set $s = set([1, 2, 3])
在创建 Set
之后,不要乱用 @a
和 @b
取决于你,因为那样的话你会违反你承诺的合同 but frozen
.
希望对您有所帮助!
序列化和反序列化可能并不像您想象的那么尴尬,因为 .perl
方法会为您将其序列化为稍后可以简单地进行 EVAL 的内容。
假设您将数组收集在数组的数组中,当您将该 AoA 添加到新的 Set
时,您可以通过地图将所有值传递给 .perl
。此时你有一组字符串。
然后您可以通过另一个映射将所有集合元素传递给 EVAL
,分配给一个变量并取回您的值。
my @v1 = 1, 2, 3;
my @v2 = 1, 2, 3;
my @vs = @v1, @v2;
my $set = set( @vs.map(*.perl) );
for $set.keys.map(&EVAL) -> @v {
say @v.^name; # Array
say @v.elems; # 3
say @v.join(', '); # 1, 2, 3
}
此外,考虑到集合的有用性,创建它们有上面的糖分,而不是完整的 Set.new
语法,即:my $set = set( @things );
或者,您也可以使用 my $set = @things.Set;
将列表强制转换为集合(前提是它不是无限的)
也许 Set is not really what you are looking for, perhaps classify
or categorize
是。
my @v1 = 1, 2, 3;
my @v2 = 1, 2, 3;
my %classified := classify *.perl, @v1, @v2;
my %categorized := categorize *.perl, @v1, @v2;
在这种特殊情况下,它们都会导致:
my Any %{Any} = "[1, 2, 3]" => $[[1, 2, 3], [1, 2, 3]]
my Any %{Any}
使用 Any for values, and Any 为键创建一个匿名散列。
两者的区别是classify
always takes the result as a single value, and categorize
总是将结果作为一个值列表,并进行分发。
我有兴趣使用 Set
来保存数组,如下所示:
my @v1 = 1, 2, 3;
my @v2 = 1, 2, 3;
my $set Set.new(@v1, @v2);
如果 Set
能够识别出这两个数组是相同的,正如使用 ~~
运算符所观察到的那样,但 Set
使用 ===
用于比较大多数对象的运算符。
# desired outcome: set([1 2 3])
# actual outcome: set([1 2 3], [1 2 3])
我 可以 在将数组添加到 Set
之前序列化数组,使用奇妙的 Set
魔法,然后反序列化。这似乎很尴尬。
我可以制作一个Setty
class,使用~~
作为比较器。这似乎是一个很好的学习,但也许是错误的。
是否有更惯用的方法来做到这一点?
这两个数组不被认为是相同的,因为它们不是值类型:即,它们在添加到集合后可以更改:
my @a = 1,2,3;
my @b = 1,2,3;
my $s = Set.new(@a,@b);
dd $s; # Set $s = set([1, 2, 3],[1, 2, 3])
@a.push(4);
dd $s; # Set $s = set([1, 2, 3, 4],[1, 2, 3])
Perl 6 中的对象标识由 .WHICH
方法确定。对于值类型,此 returns 值的唯一表示。对于像 Array
s 这样的引用类型,它 returns 根据类型及其对象 ID 唯一标识对象的东西。
目前,身份是使用 ObjAt
class 实现的,但功能仍有一些变化。但是,只要 .WHICH
方法 returns 唯一描述了 你 认为识别你的对象的东西,你应该能够创建你自己的 .WHICH
执行。例如:
role frozen {
method WHICH() {
ObjAt.new(self.join("[=11=]")) # something not occurring in values
}
}
my @a = 1,2,3;
my @b = 1,2,3;
my $s = Set.new(@a but frozen,@b but frozen);
dd $s; # Set $s = set([1, 2, 3])
在创建 Set
之后,不要乱用 @a
和 @b
取决于你,因为那样的话你会违反你承诺的合同 but frozen
.
希望对您有所帮助!
序列化和反序列化可能并不像您想象的那么尴尬,因为 .perl
方法会为您将其序列化为稍后可以简单地进行 EVAL 的内容。
假设您将数组收集在数组的数组中,当您将该 AoA 添加到新的 Set
时,您可以通过地图将所有值传递给 .perl
。此时你有一组字符串。
然后您可以通过另一个映射将所有集合元素传递给 EVAL
,分配给一个变量并取回您的值。
my @v1 = 1, 2, 3;
my @v2 = 1, 2, 3;
my @vs = @v1, @v2;
my $set = set( @vs.map(*.perl) );
for $set.keys.map(&EVAL) -> @v {
say @v.^name; # Array
say @v.elems; # 3
say @v.join(', '); # 1, 2, 3
}
此外,考虑到集合的有用性,创建它们有上面的糖分,而不是完整的 Set.new
语法,即:my $set = set( @things );
或者,您也可以使用 my $set = @things.Set;
也许 Set is not really what you are looking for, perhaps classify
or categorize
是。
my @v1 = 1, 2, 3;
my @v2 = 1, 2, 3;
my %classified := classify *.perl, @v1, @v2;
my %categorized := categorize *.perl, @v1, @v2;
在这种特殊情况下,它们都会导致:
my Any %{Any} = "[1, 2, 3]" => $[[1, 2, 3], [1, 2, 3]]
my Any %{Any}
使用 Any for values, and Any 为键创建一个匿名散列。
两者的区别是classify
always takes the result as a single value, and categorize
总是将结果作为一个值列表,并进行分发。