Xóa một số ký tự khỏi chuỗi theo chỉ mục (Raku)


15

Câu hỏi thường gặp: Trong Raku, làm thế nào để bạn xóa một số ký tự khỏi chuỗi, dựa trên chỉ mục của chúng?

Nói rằng tôi muốn xóa các chỉ số 1 đến 3 và 8

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

Câu trả lời:


14

Biến thể của Shnipersons trả lời:

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

Trong một dòng:

say '0123456789'.comb[(^* ∖ (1..3, 8).flat).keys.sort].join;

hoặc được gọi bởi một chức năng:

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

say '0123456789'.&remove: (1..3, 8);

hoặc với sự gia tăng của Str:

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

say '0123456789'.remove: (1..3, 8);

Điều đó giải quyết vấn đề hoàn toàn theo ý kiến ​​của tôi. Cảm ơn đã nhắc nhở rằng \ và (-) là tương đương. Tôi không thấy những cách khác để cắt với chỉ số tôi không muốn và không phải là chỉ số tôi muốn.
Tinmarino

1
Bạn không phải sử dụng MONKET-TYPINGnếu bạn chỉ làm cho nó trở thành phương thức nổi miễn phí và gọi nó là 'foobar'.&remove: (1..2, 4); (gia tăng có thể có vấn đề với thành phần nếu được sử dụng nhiều lần)
user0721090601

(điều này không có nghĩa là sự gia tăng là xấu, chỉ là đó .&removelà một cách để loại bỏ điều đó.
user0721090601

Tôi đã thêm các biến thể không tăng cường theo đề nghị của bạn. Cảm ơn bạn.
Sebastian

1
Khó hiểu và có vẻ như một nhân vật dấu gạch chéo ngược.
Shniperson

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

9

Ý tưởng mới nhất của tôi cho một hoạt động không hoạt động (Tôi sẽ đề cập đến việc thực hiện bên dưới):

Sử dụng:

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

Thực hiện, gói (một biến thể) giải pháp của 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

Cú pháp sử dụng toán tử mà tôi đã khai báo là string[- list-of-indices-to-be-subtracted ], bằng cách sử dụng [...]ký hiệu quen thuộc , nhưng với một chuỗi ở bên trái và một dấu trừ bổ sung sau khi mở [để chỉ ra rằng nội dung đăng ký là một danh sách các ngoại lệ thay vì chỉ mục .

[Chỉnh sửa: Tôi đã thay thế triển khai ban đầu của mình bằng Brad's. Điều đó có lẽ đã sai lầm bởi vì, như Brad lưu ý, giải pháp của anh ta "giả định rằng [exdices] theo thứ tự từ thấp nhất đến cao nhất, và không có sự chồng chéo.", Và trong khi anh ta không hứa hẹn gì khác, thì việc sử dụng [- ... ]rất gần với làm như vậy. Vì vậy, nếu đường cú pháp này được sử dụng bởi ai đó, có lẽ họ không nên sử dụng giải pháp của Brad. Có lẽ có một cách để loại bỏ giả định mà Brad đưa ra.]

Tôi thích cú pháp này nhưng tôi biết rằng Larry đã cố tình không xây dựng để sử dụng các [...]chuỗi chỉ mục nên có lẽ cú pháp của tôi ở đây không phù hợp để áp dụng rộng rãi. Có lẽ sẽ tốt hơn nếu một số ký tự dấu ngoặc khác nhau được sử dụng. Nhưng tôi nghĩ rằng việc sử dụng một cú pháp postcircumfix đơn giản là tốt.

(Tôi cũng đã cố gắng thực hiện một [ ... ]biến thể thẳng để lập chỉ mục các chuỗi theo cách chính xác giống như đối với Positionals nhưng đã không làm cho nó hoạt động vì lý do ngoài tôi tối nay. Thật kỳ lạ [+ ... ]sẽ làm việc hết sức nhưng không làm chỉ số; Không có ý nghĩa gì với tôi cả! Dù sao đi nữa, tôi sẽ đăng những gì tôi có và xem xét câu trả lời này hoàn chỉnh.)


[Chỉnh sửa: Giải pháp trên có hai khía cạnh nên được xem là khác biệt. Đầu tiên, một toán tử do người dùng định nghĩa, đường cú pháp được cung cấp bởi postcircumfix:<[- ]> (Str ...khai báo. Thứ hai, cơ thể của tuyên bố đó. Ở trên tôi đã sử dụng (một biến thể) giải pháp của Brad. Câu trả lời ban đầu của tôi là dưới đây.]


Vì câu hỏi của bạn tập trung vào việc loại bỏ một số chỉ số của a .combvà gửi lại joinkết quả, nên câu hỏi của bạn về cơ bản là một bản sao của ... [Chỉnh sửa: Sai, theo câu trả lời của Brad.]

Một cách nhanh chóng để bỏ chọn các thành phần mảng hoặc danh sách là gì? thêm nhiều giải pháp cho .comb ... .joincâu trả lời [ ] ở đây.


Được triển khai dưới dạng nhiều multis nên có thể sử dụng cùng một cú pháp với 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)

Việc sort keys ^@pos (-) @exdicestriển khai chỉ là một phiên bản hơi đơn giản của câu trả lời của @ Sebastian. Tôi chưa đánh giá nó so với giải pháp của jnthn từ câu trả lời trước đó tôi đã liên kết ở trên nhưng nếu nhanh hơn thì nó có thể được hoán đổi thay thế. * [Chỉnh sửa: Rõ ràng thay vào đó nên là giải pháp của Brad cho biến thể chuỗi.] *


"Tôi nghĩ rằng việc sử dụng một cú pháp postcircumfix đơn giản là tốt". Chắc chắn rồi! Tôi thích giải pháp này: siêu rõ ràng để đọc.
Tinmarino

8

một biến thể khác:

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

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

8

Đây là cái gần nhất tôi có được về sự đơn giản và ngắn gọn.

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

7

Mọi người đều biến chuỗi thành một danh sách bằng cách sử dụng combhoặc sử dụng danh sách phẳng các chỉ mục.

Không có lý do để làm một trong những điều đó

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

Các giả định ở trên cho rằng các chỉ số theo thứ tự từ thấp nhất đến cao nhất và không có sự trùng lặp.


Đây là câu trả lời nhanh nhất theo hệ số 150 trên máy của tôi (với my $s = "0123456789" x 1000; my $l = (1..3, 8, 40, 100, 1001, 4000..4100).flat). Comb rất dài cho chuỗi dài Cảm ơn @BradGilbert, điều này chắc chắn sẽ giúp một số người, ít nhất là tôi :-)
Tinmarino

1
@Tinmarino Đó là vì MoarVM thường không sao chép chuỗi, thay vào đó, nó tạo ra các đối tượng chuỗi con trỏ vào chuỗi gốc. Khi bạn sử dụng .combnó phải tạo ra nhiều đối tượng đó và kết hợp chúng lại với nhau. Với substrnó tạo ra càng ít các đối tượng đó càng tốt.
Brad Gilbert

"Các đối tượng chuỗi con trỏ vào chuỗi gốc": đó có phải là lý do tại sao nó được quyết định thực hiện Str là bất biến? Tối ưu hóa ấn tượng nào.
Tinmarino

5
my $string='0123456789';
for (1..3, 8).flat.reverse { $string.substr-rw($_, 1) = '' }
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.