색인으로 문자열에서 일부 문자 제거 (Raku)


15

FAQ : Raku에서 색인을 기준으로 문자열에서 일부 문자를 어떻게 제거합니까?

인덱스 1에서 3 및 8을 제거하고 싶다고 가정 해보십시오.

xxx("0123456789", (1..3, 8).flat);  # 045679

답변:


14

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);

그것은 내 의견으로는 문제를 완전히 해결합니다. \와 (-)는 동일하다는 것을 상기시켜 주셔서 감사합니다. 내가 원하지 않는 인덱스 로 슬라이스 하고 원하는 인덱스 가 아닌 다른 방법을 보지 못합니다 .
Tinmarino

1
당신은 사용할 필요가 없습니다 MONKET-TYPING당신이 그냥 방법 부동 자유 케하고 호출하는 경우 'foobar'.&remove: (1..2, 4); (여러 번 사용하는 경우 기능 보강이 구성에 문제가있을 수 있습니다)
user0721090601

(증강이 나쁘다는 것은 아닙니다. 단지 그것을 .&remove제거하는 방법
일뿐

귀하의 제안에 비 확대 변형을 추가했습니다. 감사합니다.
세바스찬

1
혼란스럽고 백 슬래시 문자처럼 보입니다.
Shniperson

12
.value.print if .key  !(elem) (1,2,3,8) for '0123456789'.comb.pairs

9

비 작업에 대한 나의 최신 아이디어 (아래 구현을 다룰 것입니다) :

용법:

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 목록임을 나타냅니다 .

[편집 : 원래 구현을 Brad의 것으로 교체했습니다. 브래드가 지적한 것처럼 그의 해결책은 "[지수]가 가장 낮은 순서에서 가장 높은 순서로 겹치지 않는다고 가정하고"다른 방법으로는 약속하지 않기 때문에 아마도 잘못된 방향 일 것이다.[- ... ] 무섭게 가까운입니다 그렇게 따라서이 구문 설탕을 누군가가 사용하려면 Brad의 솔루션을 사용하지 않아야합니다. 아마도 브래드의 가정을 제거 할 수있는 방법이있을 것입니다.]

나는이 구문을 좋아하지만 래리는 의도적으로했다는 것을 알고 있지 의 사용에 구축 [...]인덱스 스트링 그래서 아마 여기에 내 구문은 널리 채택 부적절하다. 다른 브라케팅 문자를 사용하면 더 좋을 것입니다. 그러나 간단한 postcircumfix 구문을 사용하는 것이 좋습니다.

(또한 s [ ... ]와 똑같은 방식으로 문자열을 인덱싱 하기위한 직선 변형 을 구현하려고했지만 Positional오늘 밤 저를 넘어서서 작동하지 못했습니다. 기묘 [+ ... ]하게는 exdices를 수행하지만 인덱스는하지 않습니다. 어쨌든, 나는 내가 가진 것을 게시 하고이 답변을 완료 한 것으로 간주합니다.)


[편집 : 위의 솔루션에는 두 가지 측면이 있습니다. 먼저, 사용자 정의 연산자 postcircumfix:<[- ]> (Str ...인 선언문에서 제공하는 구문 설탕 . 둘째, 그 선언의 본문. 위에서 나는 Brad의 솔루션을 사용했다. 내 원래 답변은 다음과 같습니다.]


귀하의 질문의 일부 인덱스를 제거 아래로 비등하기 때문에 .comb, 다시 join결과를 보내고, 당신의 질문의 ... 중복 본질적으로 [편집 :. 틀렸어, 브래드의 대답 당은]

배열 또는 목록 요소를 선택 해제하는 빠른 방법은 무엇입니까? .comb ... .join여기에 [ ] 답변에 대한 추가 솔루션이 추가 되었습니다.


동일한 구문을 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)

sort keys ^@pos (-) @exdices구현은 세바스찬의 대답 @의 약간 단순화 된 버전입니다. 위에서 링크 한 이전 답변의 jnthn 솔루션에 대해 벤치 마크하지 않았지만 더 빠르면 대신 교체 할 수 있습니다. * [편집 : 분명히 문자열 변형에 대한 Brad의 솔루션 이어야합니다 .] *


"간단한 postcircumfix 구문을 사용하는 것이 좋습니다" 확실히! 나는이 솔루션을 좋아합니다 : 읽기 명확합니다.
Tinmarino

8

또 다른 변형 :

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

.print for ((0..9) (-) (1,2,3,8)).keys;

8

이것은 단순성과 부족 성 측면에서 가장 가깝습니다.

say '0123456789'.comb[ |(3..6), |(8..*) ].join

7

모두가 문자열을 목록으로 바꾸고 있습니다. 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

위의 표는 지수가 가장 낮은 순서에서 가장 높은 순서이며 중첩이 없다고 가정합니다.


내 컴퓨터에서 (가있는 my $s = "0123456789" x 1000; my $l = (1..3, 8, 40, 100, 1001, 4000..4100).flat) 150 배로 가장 빠른 답변입니다 . 빗은 긴 문자열을 위해 길다. @BradGilbert에게 감사한다. 이것은 적어도 어떤 사람들에게 도움이 될 것이다. :-)
Tinmarino

1
@Tinmarino MoarVM은 일반적으로 문자열을 복사하지 않고 대신 원래 문자열을 가리키는 하위 문자열 객체를 만듭니다. 당신이 .comb그것을 사용할 때 많은 객체를 생성하고 함께 결합해야합니다. 함께 substr그것을 가능한 한 해당 개체의 몇 가지로 만듭니다.
브래드 길버트

"원래 문자열을 가리키는 하위 문자열 객체": Str을 변경 불가능한 것으로 구현하기로 결정한 이유는 무엇입니까? 어쨌든 인상적인 최적화.
Tinmarino

5
my $string='0123456789';
for (1..3, 8).flat.reverse { $string.substr-rw($_, 1) = '' }
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.