arrays - perl6取消选择数组或列表元素的快速方法是什么?




set deselect (3)

对于大型数组而言,这可能会很慢,但从逻辑上讲,它更接近您正在寻找的内容:

my @a = <a b c d>;

say (@a ⊖ @a[0,1]).keys; # (c d)

它基本上与你在开始时提出的解决方案一样,使用集合差异,除了它在整个数组而不是索引上使用它。 此外,在某些情况下,您可以直接使用该集; 这取决于你想做什么。

要在perl6中从数组中选择多个元素,这很容易:只需使用索引列表:

> my @a = < a b c d e f g >;
> @a[ 1,3,5 ]
(b d f)

但要取消选择那些元素,我不得不使用Set:

> say @a[ (@a.keys.Set (-) (1,3,5)).keys.sort ]
(a c e g)

我想知道是否有更简单的方法因为我使用的数组通常很大?


这是另一种选择:

my @a = < a b c d e f g >;
say @a[@a.keys.grep(none(1, 3, 5))];

但总而言之,数组并未针对此用例进行优化。 它们针对使用单个元素或所有元素进行了优化,并且切片为按键提供(正面)选择多个元素的快捷方式。

如果您告诉我们潜在的用例,也许我们可以推荐一个更合适的数据结构。


sub infix:<not-at> ($elems, @not-ats) {
  my $at = 0;
  flat gather for @not-ats -> $not-at {
    when $at < $not-at { take $at++ xx $not-at - $at } 
    NEXT { $at++ }
    LAST { take $at++ xx $elems - $not-at - 1 }
  }
}

my @a = < a b c d e f g >;
say @a[ * not-at (1, 3, 5) ]; # (a c e g)

如果您知道它使用的每个P6结构,我认为运算符代码是不言自明的。 如果有人愿意接受以下内容的解释,请在评论中告诉我。

我将从生成 not-at 调用的两个方面开始。

* 又名 Whatever

Whatever doc页面

* 用于术语位置时,即作为操作数,与大多数运算符组合使用时,编译器会将表达式转换为 WhateverCode 类型的闭包

* 确实在上面用作操作数。 在这种情况下,它是我刚创建的中缀 not-at 运算符的左参数(对应于 $elems 参数)。

接下来的问题是,编译器会进行转换吗? 编译器根据运算符是否具有显式 * 作为与 * 参数对应的参数来决定。 如果我写了 * 而不是 $elems 那么那就 not-at 少数几个想要直接处理 * 并做任何选择的操作符之一而且编译器会直接调用它。 但我没有。 我写了 $elems 。 所以编译器会完成我接下来要描述的转换。

转换在封闭表达式周围构建一个新的 WhateverCode ,并重写 Whatever as“it”又名为 $_ 的主题。 所以在这种情况下它转为:

* not-at (1,3,5)

进入这个:

{ $_ not-at (1,3,5) }

作为下标的内容是什么

@a[...] 中的 @a[...] 是一个 Positional (数组/列表)下标。 这提出了几个评估方面,其中两个问题在这里:

  • “它”又名为 $_ 的主题设置为列表/数组的长度。

  • 如果下标的内容是 Callable 则会 Callable 它。 如上所述生成的 WhateverCode 确实是 Callable 因此它被调用。

所以这:

@a[ * not-at (1,3,5) ]

成为这个:

@a[ { $_ not-at [1,3,5] } ]

变成这样:

 @a[ { infix:not-at(7, [1,3,5]) } ]




deselect