我将如何使用 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 魔法,然后反序列化。这似乎很尴尬。

可以制作一个Settyclass,使用~~作为比较器。这似乎是一个很好的学习,但也许是错误的。

是否有更惯用的方法来做到这一点?

这两个数组不被认为是相同的,因为它们不是值类型:即,它们在添加到集合后可以更改:

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 值的唯一表示。对于像 Arrays 这样的引用类型,它 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总是将结果作为一个值列表,并进行分发。