如果不知道一个数组元素的索引,删除该元素的语法是什么?

10

如果您知道数组元素的索引,可以在Perl 6中使用副词:delete删除该元素:

my @letters = <a b c>; @letters[0]:delete; say @letters
# OUTPUT: «[(Any) b c]␤»

然而,如果你不知道索引,就无法做到这一点:

my @letters = <a b c>; $_:delete if $elem eq 'a' for @letters
#ERROR! → Variable '$_:delete' is not declared

如果您声明循环变量is rw,仍然存在相同的问题:
my @letters = <a b c>; for @letters -> $l is rw { $l:delete if $l eq 'a' }; say @letters
#ERROR! → Variable '$l:delete' is not declared

似乎没有其他删除数组元素的方法。实际上,相当于Perl 5的delete指向该副词。您可以使用splice,但是再次必须知道索引。实现似乎是此函数,DELETE-POS,它需要有效地知道数组索引。
因此,问题是,如标题所述,如果您只有元素本身的句柄而不是其索引,那么是否有一种删除数组(或关联数组)元素的方法?

2
正如错误信息所表明的那样,语法$foo:bar是一个单一标识符,而不是与:delete副词相结合的标识符。从语法上讲,:delete必须跟随一个显式的下标运算符(例如[...])才能被解释为副词。我猜你知道这一点,但我想为以后阅读此内容的其他人发表评论。 - raiph
2个回答

8

取决于你如何定义“删除”。在数组内部,执行DELETE-POS会将数组中的元素绑定到nqp::null,这将丢弃该位置处的任何容器。在 HLL 级别上,这由数组的类型表示:

my Str @letters = <a b c>;
@letters[1]:delete;
say @letters;   # [a (Str) c]

然而,通过分配Nil您也可以实现相同的效果:

my Str @letters = <a b c>;
@letters[1] = Nil;
say @letters;   # [a (Str) c]

在这种情况下,该元素的容器保持不变,您只需将其恢复到其“自然”状态即可。如果您对这种类型的删除感到满意,您也可以在循环中使用它:
my Str @letters = <a b c>;
$_ = Nil if $_ eq "b" for @letters;
say @letters;   # [a (Str) c]

当我说“恢复到其自然状态”时,这也包括任何默认值:
my Str @letters is default<foo> = <a b c>;
$_ = Nil if $_ eq "b" for @letters;
say @letters;   # [a foo c]

如果你想真正从列表中删除元素,而不保留现有元素的位置,当然可以使用grep

my @letters = <a b c>;
@letters .= grep: * ne "b";
say @letters;  # [a c]

但这似乎不是你想要的。

5
请阅读Lizmat的答案,她对您的标题问题进行了深入思考和有益的分析,并恰当地关注了英语单词“deleting”的歧义性。
以下是将她答案中的一个建议转化为使用:delete副词的方法,以便最终的@letters仍然是相同的数组,第一个元素被:delete删除,因此结果与您的原始结果相同([(Any) b c])。
my @letters = <a b c>;
.[.grep: 'a', :k]:delete given @letters;
say @letters;
< p > 在 grep 命令中使用 :k 副词,表示希望返回结果的索引。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接