Видаліть деякі символи з рядка за індексом (Раку)


15

FAQ: Як у Raku видалити деякі символи з рядка, виходячи з їх індексу?

Скажіть, я хочу видалити індекси 1 - 3 та 8

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

Відповіді:


14

Варіант відповіді Шніперсона:

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); (augment може мати проблеми зі складом, якщо використовується кілька разів)
user0721090601

(що не скаже, що розширення погано, просто .&removeце спосіб видалити це.
user0721090601

До вашої пропозиції я додав варіант без збільшення. Дякую.
Себастьян

1
∖ заплутаний і здається символом зворотної косої риси.
Шніперсон


9

Моя остання ідея щодо недіяльної роботи (я розповім про реалізацію нижче):

Використання:

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

Реалізація, обгортання (варіант) рішення Бреда:

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 ], тобто, використовуючи знайомі [...]позначення, але з рядком зліва та додатковим мінусом після відкриття, [щоб вказати, що вміст підрозділу - це перелік експедицій, а не індекси .

[Редагувати: Я замінив свою оригінальну реалізацію на Бреду. Це, мабуть, неправильно, тому що, як зазначає Бред, його рішення "передбачає, що [експедиції] знаходяться в порядку від найнижчого до найвищого і немає перекриття", і, хоча його не обіцяє інакше, використання [- ... ]жахливо близьке до роблячи так. Отже, якщо цей синтаксичний цукор мав би хтось використовувати, він, ймовірно, не повинен використовувати рішення Бреда. Можливо, є спосіб усунути припущення Бреда.]

Мені подобається цей синтаксис, але я усвідомлюю, що Ларрі навмисно не створив використання [...]індексуючих рядків, тому, можливо, мій синтаксис тут є недоцільним для широкого прийняття. Можливо, було б краще, якби були використані різні символи брекетування. Але я думаю, що використання простого синтаксису postcircumfix є приємним.

(Я також намагався реалізувати прямий [ ... ]варіант для індексації рядків точно так само, як і для Positionals, але сьогодні не вдалося змусити його працювати з причин, що знаходяться поза мною. Дивно [+ ... ]працюватимуть, щоб робити exdices, але не робити індекси; це робить для мене немає сенсу! Так чи інакше, я опублікую те, що маю, і вважаю цю відповідь повною.)


[Редагувати: вищезазначене рішення має два аспекти, які слід розглядати як виразні. По-перше, визначений користувачем оператор, синтаксичний цукор, наданий postcircumfix:<[- ]> (Str ...декларацією. По-друге, суть цієї декларації. У вищесказаному я використав (варіант) рішення Бреда. Моя оригінальна відповідь нижче.]


Оскільки ваше запитання зводиться до видалення деяких індексів .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 з попередньої відповіді, яку я зв'язав вище, але якщо це швидше, то натомість можна замінити її. * [Редагувати: Очевидно, це замість цього має бути рішення Бреда для варіанту рядка.] *


"Я думаю, що використання простого синтаксису postcircumfix є приємним". Безумовно ! Я люблю це рішення: дуже зрозуміло для читання.
Tinmarino


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

Вищесказане передбачає, що показники є в порядку від найнижчого до найвищого, і немає перекриття.


Це найшвидша відповідь на коефіцієнт 150 на моїй машині (з my $s = "0123456789" x 1000; my $l = (1..3, 8, 40, 100, 1001, 4000..4100).flat). Гребінець довгі струни Дякую @BradGilbert, це, безумовно, допоможе деяким людям, принаймні мені :-)
Tinmarino

1
@Tinmarino Це тому, що MoarVM зазвичай не копіює рядки, натомість створює об'єкти підрядків, які вказують на початковий рядок. Коли ви користуєтесь .combним, ви повинні створити багато цих об'єктів і об'єднати їх назад разом. З substrйого допомогою створюється якомога менше таких об’єктів.
Бред Гілберт

"підрядкові об'єкти, які вказують на початковий рядок": це те, чому було вирішено реалізувати Str як незмінний? Вражаюча оптимізація все одно.
Tinmarino

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.