通过索引从字符串中删除一些字符(Raku)

tin*_*ino 15 raku

常见问题解答:在 Raku 中,如何根据索引从字符串中删除一些字符?

假设我想删除索引 1 到 3 和 8

xxx("0123456789", (1..3, 8).flat);  # 045679
Run Code Online (Sandbox Code Playgroud)

Seb*_*ian 14

Shnipersons 的变体回答:

my $a='0123456789';
with $a {$_=.comb[(^* ? (1..3, 8).flat).keys.sort].join};
say $a;
Run Code Online (Sandbox Code Playgroud)

在一行中:

say '0123456789'.comb[(^* ? (1..3, 8).flat).keys.sort].join;
Run Code Online (Sandbox Code Playgroud)

或由函数调用:

sub remove($str, $a) {
    $str.comb[(^* ? $a.flat).keys.sort].join;
}

say '0123456789'.&remove: (1..3, 8);
Run Code Online (Sandbox Code Playgroud)

或增加 Str:

use MONKEY-TYPING;
augment class Str {
    method remove($a) {
        $.comb[(^* ? $a.flat).keys.sort].join;
    }
};

say '0123456789'.remove: (1..3, 8);
Run Code Online (Sandbox Code Playgroud)


che*_*nyf 12

.value.print if .key  !(elem) (1,2,3,8) for '0123456789'.comb.pairs
Run Code Online (Sandbox Code Playgroud)


rai*_*iph 9

我对 not-at 操作的最新想法(我将在下面介绍实现):

用法:

say '0123456789'[- 1..3, 8 ]; # 045679
Run Code Online (Sandbox Code Playgroud)

实现,包装(一个变体)布拉德的解决方案:

multi postcircumfix:<[- ]> (|args) { remove |args }

sub remove( Str:D $str is copy, +@exdices){
    for @exdices.reverse {
        when Int   { $str.substr-rw($_,1) = '' }
        when Range { $str.substr-rw($_  ) = '' }
    }
    $str
}

say '0123456789'[- 1..3, 8 ]; # 045679
Run Code Online (Sandbox Code Playgroud)

要使用的语法我已经声明是运营商string[- list-of-indices-to-be-subtracted ]使用熟悉的,即[...]符号,但在左边的字符串,并开放后的额外减[,表明标内容的列表exdices而不是指数

[编辑:我已经用布拉德的替换了我原来的实现。这可能是错误的,因为正如 Brad 指出的那样,他的解决方案“假设 [exdices] 按从低到高的顺序排列,并且没有重叠。”虽然他没有承诺否则, using[- ... ]非常接近这样做。因此,如果有人要使用这种语法糖,他们可能不应该使用 Brad 的解决方案。也许有一种方法可以消除布拉德的假设。]

我喜欢这种语法,但我知道,拉里故意使用的建立[...]索引字符串,这样也许我在这里的语法是不合适的广泛采用。如果使用一些不同的括号字符,也许会更好。但我认为使用简单的 postcircumfix 语法很好。

(我还尝试以[ ... ]Positionals完全相同的方式实现用于索引字符串的直接变体,但由于今晚我以外的原因未能使其正常工作。奇怪的是,[+ ... ]将努力进行 exdices 但不进行索引;这使得对我来说根本没有意义!无论如何,我会发布我所拥有的并认为这个答案是完整的。)


[编辑:上述解决方案有两个方面应该被视为不同的。首先,一个用户定义的运算符,由postcircumfix:<[- ]> (Str ..., 声明提供的语法糖。其次,该声明的正文。在上面我使用了(一种变体)Brad 的解决方案。我的原始答案如下。]


因为您的问题归结为删除 a 的某些索引.comb并重新join计算结果,所以您的问题本质上是 ... [编辑:错误,根据布拉德的回答。]

取消选择数组或列表元素的快速方法是什么?.comb ... .join在此处为 [ ] 答案添加了更多解决方案。


实现为两个 multis,因此相同的语法可以与Positionals一起使用:

multi postcircumfix:<[- ]> (Str $_, *@exdex) { .comb[- @exdex ].join }

multi postcircumfix:<[- ]> (@pos,   *@exdex) { sort keys ^@pos (-) @exdex } 

say '0123456789'[- 1..3, 8 ]; # 045679

say (0..9)[- 1..3, 8 ];       # (0 4 5 6 7 9)
Run Code Online (Sandbox Code Playgroud)

sort keys ^@pos (-) @exdices实现只是@Sebastian 答案的略微简化版本。我还没有根据我上面链接的较早答案中的 jnthn 解决方案对其进行基准测试,但如果速度更快,则可以将其替换。*[编辑:显然它应该是布拉德的字符串变体解决方案。]*

  • @jubilatious1如果有人不喜欢“-”,他们可以选择一个不同的字符/字符串来表示“排除这些”。也许“[除了...]”?简洁是这个答案的灵魂,所以我会更高兴“[不是...]”。更一般地说,这些事情有些主观。注意@Tinmarino 的反应。需要明确的是,“-”在数字加/减意义上并不是“负”,而是在正则表达式字符类意义上——“&lt;-[abc]&gt;”,即“排除这些”。它只是“负面出现”,因为它是“-”,一个字符,就像“负面出现”一样。在后者中,它被理解为“连字符”。 (2认同)

Shn*_*son 8

另一个变种:

print $_[1] if $_[0] !(elem) (1,2,3,8) for ^Inf Z 0..9;

.print for ((0..9) (-) (1,2,3,8)).keys;
Run Code Online (Sandbox Code Playgroud)


Hol*_*lli 8

这是我在简单性和简短性方面最接近的。

say '0123456789'.comb[ |(3..6), |(8..*) ].join
Run Code Online (Sandbox Code Playgroud)


Bra*_*ert 8

每个人都在使用comb或使用索引的平面列表将字符串转换为列表。

没有理由做这两件事

sub remove( Str:D $str is copy, +@indices ){
    for @indices.reverse {
        when Int   { $str.substr-rw($_,1) = '' }
        when Range { $str.substr-rw($_  ) = '' }
    }
}

remove("0123456789",  1..3, 8 );  # 045679
remove("0123456789", [1..3, 8]);  # 045679
Run Code Online (Sandbox Code Playgroud)

上面假设索引是从低到高的顺序,没有重叠。


Seb*_*ian 5

my $string='0123456789';
for (1..3, 8).flat.reverse { $string.substr-rw($_, 1) = '' }
Run Code Online (Sandbox Code Playgroud)