Удалить некоторые символы из строки по индексу (Raku)

15

FAQ: Как удалить некоторые символы из строки в Raku, основываясь на их индексе?

Скажем, я хочу удалить индексы с 1 по 3 и 8

xxx("0123456789", (1..3, 8).flat);  # 045679
Tinmarino
источник

Ответы:

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);
Себастьян
источник
Это решает проблему полностью по моему мнению. Спасибо за напоминание, что \ и (-) эквивалентны. Я не вижу других способов срезать с индексом, который мне не нужен, а не с индексами, которые я хочу.
Тинмарино
1
Вам не нужно использовать, MONKET-TYPINGесли вы просто делаете метод free float и вызываете его как 'foobar'.&remove: (1..2, 4); (augment может иметь проблемы с композицией, если используется несколько раз)
user0721090601
(что не означает, что увеличение является плохим, просто .&removeэто способ удалить это.
user0721090601
Я добавил вариант без дополнения к вашему предложению. Спасибо.
Себастьян
1
∖ сбивает с толку и выглядит как символ обратной косой черты.
Шниперсон
12
.value.print if .key  !(elem) (1,2,3,8) for '0123456789'.comb.pairs
chenyf
источник
9

Моя последняя идея для операции not-at (я расскажу о реализации ниже):

Применение:

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

[Редактировать: я заменил мою оригинальную реализацию на Брэда. Это, вероятно, неправильно, потому что, как отмечает Брэд, его решение «предполагает, что [exdices] находятся в порядке от низшего к высшему, и нет перекрытия», и, хотя он не обещает иначе, использование [- ... ]очень близко к делать это. Так что, если этот синтаксис сахар должен был использоваться кем-то, он, вероятно, не должен использовать решение Брэда. Возможно, есть способ опровергнуть предположение Брэда.]

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

(Я также попытался реализовать прямой [ ... ]вариант для индексации строк точно так же, как для Positionals, но не смог заставить его работать по независящим от меня причинам сегодня вечером. Странно [+ ... ]будет работать, чтобы добиться успеха, но не сделать индексы; нет никакого смысла для меня вообще! Во всяком случае, я опубликую то, что у меня есть, и считаю этот ответ полным.)


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

raiph
источник
«Я думаю, что использование простого синтаксиса postcircumfix хорошо». Определенно! Я люблю это решение: супер ясно читать.
Тинмарино
8

еще другие варианты:

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

.print for ((0..9) (-) (1,2,3,8)).keys;
Shniperson
источник
8

Это самое близкое, что я получил с точки зрения простоты и краткости.

say '0123456789'.comb[ |(3..6), |(8..*) ].join
Holli
источник
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 как неизменяемый? Впечатляющая оптимизация в любом случае.
Тинмарино
5
my $string='0123456789';
for (1..3, 8).flat.reverse { $string.substr-rw($_, 1) = '' }
Себастьян
источник