按索引从字符串中删除一些字符 (Raku)
Remove some characters from a string by index (Raku)
常见问题解答:在 Raku 中,如何根据索引从字符串中删除一些字符?
假设我要删除索引 1 到 3 和 8
xxx("0123456789", (1..3, 8).flat); # 045679
.value.print if .key !(elem) (1,2,3,8) for '0123456789'.comb.pairs
另一种变体:
print $_[1] if $_[0] !(elem) (1,2,3,8) for ^Inf Z 0..9;
.print for ((0..9) (-) (1,2,3,8)).keys;
my $string='0123456789';
for (1..3, 8).flat.reverse { $string.substr-rw($_, 1) = '' }
这是我得到的最接近简洁和简短的版本。
say '0123456789'.comb[ |(3..6), |(8..*) ].join
Shnipersons 答案的变体:
my $a='0123456789';
with $a {$_=.comb[(^* ∖ (1..3, 8).flat).keys.sort].join};
say $a;
一行:
say '0123456789'.comb[(^* ∖ (1..3, 8).flat).keys.sort].join;
或由函数调用:
sub remove($str, $a) {
$str.comb[(^* ∖ $a.flat).keys.sort].join;
}
say '0123456789'.&remove: (1..3, 8);
或增加 Str:
use MONKEY-TYPING;
augment class Str {
method remove($a) {
$.comb[(^* ∖ $a.flat).keys.sort].join;
}
};
say '0123456789'.remove: (1..3, 8);
我对 not-at 操作的最新想法(我将在下面介绍实现):
用法:
say '0123456789'[- 1..3, 8 ]; # 045679
Brad 解决方案的实施、包装(变体):
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
使用我声明的运算符的语法是 string[- list-of-indices-to-be-subtracted ]
,即使用熟悉的 [...]
表示法,但在左侧有一个字符串,在开头 [
表示下标内容是exdices的列表而不是indices.
[编辑:我已经用 Brad 的替换了我原来的实现。这可能是错误的,因为正如 Brad 指出的那样,他的解决方案 "assumes that the [exdices] are in order from lowest to highest, and there is no overlap.",虽然他没有承诺,但使用 [- ... ]
非常接近这样做。因此,如果有人要使用这种语法糖,他们可能不应该使用 Brad 的解决方案。也许有一种方法可以消除 Brad 所做的假设。]
我喜欢这种语法,但我知道 Larry 故意 而不是 构建使用 [...]
来索引字符串,所以我这里的语法可能不适合广泛采用。如果使用一些不同的括号字符可能会更好。但我认为使用简单的 postcircumfix 语法很好。
(我还尝试实现一个直接的 [ ... ]
变体来以与 Positional
s 完全相同的方式索引字符串,但今晚由于我以外的原因未能使其工作. 奇怪的是 [+ ... ]
会做 exdices 而不是做索引;这对我来说根本没有意义!无论如何,我会 post 我有什么并认为这个答案完整。)
[编辑:上述解决方案有两个方面应该被视为截然不同的。首先,一个用户定义的运算符,由 postcircumfix:<[- ]> (Str ...
声明提供的语法糖。第二,该声明的正文。在上面我使用了 Brad 的解决方案(的变体)。我的原始答案如下。]
因为您的问题归结为删除 .comb
的一些索引并重新join
结果,您的问题本质上是 ...[= 的重复68=] [编辑:错误,根据 Brad 的回答。]
在此处为 [.comb ... .join
] 答案添加了更多解决方案。
作为两个 multis 实现,因此相同的语法可用于 Positional
s:
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)
sort keys ^@pos (-) @exdices
实现只是@Sebastian 答案的略微简化版本。我没有根据上面链接的早期答案将其与 jnthn 的解决方案进行基准测试,但如果速度更快,则可以将其换入。 *[编辑:显然它应该是 Brad 的 字符串变体解决方案。]*
每个人要么使用 comb
将字符串转换为列表,要么使用索引的平面列表。
没有理由做这两件事
sub remove( Str:D $str is copy, +@indices ){
for @indices.reverse {
when Int { $str.substr-rw($_,1) = '' }
when Range { $str.substr-rw($_ ) = '' }
}
$str
}
remove("0123456789", 1..3, 8 ); # 045679
remove("0123456789", [1..3, 8]); # 045679
以上假设指数从低到高排列,没有重叠。
我知道这是一个老掉牙的问题,但这里有另一个版本,它采用与 Brad Gilbert 的 substr-rw
解决方案类似的方法,但避免了需要就地编辑字符串(因此更适合函数式编程思维):
sub remove(Str:D $str, +@indices) {
($str, |@indices.reverse).reduce: -> $_, $idx {
{ S/.**{$idx.head} <(.**{$idx.elems})> .*// }}
}
say remove "0123456789", 1..3, 8; # OUTPUT: «045679»
say remove "0123456789", [1..3, 8]; # OUTPUT: «045679»
当两者都包含在一个函数中时,这与 substr-rw
解决方案 没有什么不同。但上面的版本有助于更好地内联使用,至少我是这样的:
say S/.**5 <(.**3)> .*// with "0123456789"; # OUTPUT: «0123489»
而不是
say do with "0123456789" -> $_ is copy { .substr-rw(5..7) = ''; $_ } # OUTPUT: «0123489»
但是请注意,基于 S///
的方法并不比 .comb
方法快,因此使用 .substr-rw
可能在性能关键领域很有用。
常见问题解答:在 Raku 中,如何根据索引从字符串中删除一些字符?
假设我要删除索引 1 到 3 和 8
xxx("0123456789", (1..3, 8).flat); # 045679
.value.print if .key !(elem) (1,2,3,8) for '0123456789'.comb.pairs
另一种变体:
print $_[1] if $_[0] !(elem) (1,2,3,8) for ^Inf Z 0..9;
.print for ((0..9) (-) (1,2,3,8)).keys;
my $string='0123456789';
for (1..3, 8).flat.reverse { $string.substr-rw($_, 1) = '' }
这是我得到的最接近简洁和简短的版本。
say '0123456789'.comb[ |(3..6), |(8..*) ].join
Shnipersons 答案的变体:
my $a='0123456789';
with $a {$_=.comb[(^* ∖ (1..3, 8).flat).keys.sort].join};
say $a;
一行:
say '0123456789'.comb[(^* ∖ (1..3, 8).flat).keys.sort].join;
或由函数调用:
sub remove($str, $a) {
$str.comb[(^* ∖ $a.flat).keys.sort].join;
}
say '0123456789'.&remove: (1..3, 8);
或增加 Str:
use MONKEY-TYPING;
augment class Str {
method remove($a) {
$.comb[(^* ∖ $a.flat).keys.sort].join;
}
};
say '0123456789'.remove: (1..3, 8);
我对 not-at 操作的最新想法(我将在下面介绍实现):
用法:
say '0123456789'[- 1..3, 8 ]; # 045679
Brad 解决方案的实施、包装(变体):
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
使用我声明的运算符的语法是 string[- list-of-indices-to-be-subtracted ]
,即使用熟悉的 [...]
表示法,但在左侧有一个字符串,在开头 [
表示下标内容是exdices的列表而不是indices.
[编辑:我已经用 Brad 的替换了我原来的实现。这可能是错误的,因为正如 Brad 指出的那样,他的解决方案 "assumes that the [exdices] are in order from lowest to highest, and there is no overlap.",虽然他没有承诺,但使用 [- ... ]
非常接近这样做。因此,如果有人要使用这种语法糖,他们可能不应该使用 Brad 的解决方案。也许有一种方法可以消除 Brad 所做的假设。]
我喜欢这种语法,但我知道 Larry 故意 而不是 构建使用 [...]
来索引字符串,所以我这里的语法可能不适合广泛采用。如果使用一些不同的括号字符可能会更好。但我认为使用简单的 postcircumfix 语法很好。
(我还尝试实现一个直接的 [ ... ]
变体来以与 Positional
s 完全相同的方式索引字符串,但今晚由于我以外的原因未能使其工作. 奇怪的是 [+ ... ]
会做 exdices 而不是做索引;这对我来说根本没有意义!无论如何,我会 post 我有什么并认为这个答案完整。)
[编辑:上述解决方案有两个方面应该被视为截然不同的。首先,一个用户定义的运算符,由 postcircumfix:<[- ]> (Str ...
声明提供的语法糖。第二,该声明的正文。在上面我使用了 Brad 的解决方案(的变体)。我的原始答案如下。]
因为您的问题归结为删除 .comb
的一些索引并重新join
结果,您的问题本质上是 ...[= 的重复68=] [编辑:错误,根据 Brad 的回答。]
.comb ... .join
] 答案添加了更多解决方案。
作为两个 multis 实现,因此相同的语法可用于 Positional
s:
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)
sort keys ^@pos (-) @exdices
实现只是@Sebastian 答案的略微简化版本。我没有根据上面链接的早期答案将其与 jnthn 的解决方案进行基准测试,但如果速度更快,则可以将其换入。 *[编辑:显然它应该是 Brad 的 字符串变体解决方案。]*
每个人要么使用 comb
将字符串转换为列表,要么使用索引的平面列表。
没有理由做这两件事
sub remove( Str:D $str is copy, +@indices ){
for @indices.reverse {
when Int { $str.substr-rw($_,1) = '' }
when Range { $str.substr-rw($_ ) = '' }
}
$str
}
remove("0123456789", 1..3, 8 ); # 045679
remove("0123456789", [1..3, 8]); # 045679
以上假设指数从低到高排列,没有重叠。
我知道这是一个老掉牙的问题,但这里有另一个版本,它采用与 Brad Gilbert 的 substr-rw
解决方案类似的方法,但避免了需要就地编辑字符串(因此更适合函数式编程思维):
sub remove(Str:D $str, +@indices) {
($str, |@indices.reverse).reduce: -> $_, $idx {
{ S/.**{$idx.head} <(.**{$idx.elems})> .*// }}
}
say remove "0123456789", 1..3, 8; # OUTPUT: «045679»
say remove "0123456789", [1..3, 8]; # OUTPUT: «045679»
当两者都包含在一个函数中时,这与 substr-rw
解决方案 没有什么不同。但上面的版本有助于更好地内联使用,至少我是这样的:
say S/.**5 <(.**3)> .*// with "0123456789"; # OUTPUT: «0123489»
而不是
say do with "0123456789" -> $_ is copy { .substr-rw(5..7) = ''; $_ } # OUTPUT: «0123489»
但是请注意,基于 S///
的方法并不比 .comb
方法快,因此使用 .substr-rw
可能在性能关键领域很有用。