[.NET] мультизамена.
А как-нибудь прям сразу, за один проход нельзя?КМП на Боре

Если есть строка abcd и правила ab -> lala; abc -> lala, результатом Replace будет lalad или lalacd?
если уж совсем лениво - то можно к результирующим строками приписать какой-нить символ/строку которого точно нигде нет, а потом его/её вычистить.
А если такого символа нет? В Unicode всего-то 65k символов. Ну т.е. конечно такое решение покатит для ситуации завтра война, но оно слишком сильно напоминает тупое решение с null-terminated strings
В таком случае - самый длинный, наверное.
просто я не понимаю в чём проблема. тупое решение очевидно.
требуется оптимальное по скорости, по памяти или по числу нажатых кнопок для написания?
требуется оптимальное по скорости, по памяти или по числу нажатых кнопок для написания?
Самый длинный результат (lalacd) или применяется самое длинное правило (abc -> lala, т.е. lalad)?
Правильное решение должно работать на любой строке. Бывают ситуации, когда устраивают и неправильные решения, но, если есть время, всегда лучше уберечь себя от возможной головной боли от того, что у заказчика программа как-то странно валится на валидных данных
> А как-нибудь прям сразу, за один проход нельзя?
можно, достаточно написать простенький автомат
можно, достаточно написать простенький автомат
Дык я ж написал - всё меняем на гуиды, потом все гуиды меняем обратно - и надеемся, что гуиды достаточно уникальны =)
Дополнительно надеемся, что среди замен нету "0" -> "1", которая наверняка убъёт любой гуид.
Самое правильное, конечно, это сгруппировать все замены ("a1"->"b1", "a2"->"b2" ...) в "(a1)|(a2)|...", дальше сказать Match, дальше пройтись по всем матчам, выяснить, какая именно подскобка сработала в каждом случае и построить новую строчку. Так я и сделаю, пожалуй.
Но!
Если б где-нибудь найти движок типа регесов, но с возможностью более тонкого контроля над работой построенного НКА, можно было бы такие вещи делать жутко быстро.
Дополнительно надеемся, что среди замен нету "0" -> "1", которая наверняка убъёт любой гуид.
Самое правильное, конечно, это сгруппировать все замены ("a1"->"b1", "a2"->"b2" ...) в "(a1)|(a2)|...", дальше сказать Match, дальше пройтись по всем матчам, выяснить, какая именно подскобка сработала в каждом случае и построить новую строчку. Так я и сделаю, пожалуй.
Но!
Если б где-нибудь найти движок типа регесов, но с возможностью более тонкого контроля над работой построенного НКА, можно было бы такие вещи делать жутко быстро.
Самая длинная левая часть, очевидно.
Вот-вот! А писать "простенький автомат" с нуля что-то не хочется.
В Unicode всего-то 65k символов.их там может быть больше,
и для подобных целей там оставлены несколько позиций.
так что нужно только посмотреть конкретные значения.
ИМХО это лучший и наибыстрейший вариант.
> Вот-вот! А писать "простенький автомат" с нуля что-то не хочется
так что-то он совсем простой - фактически на два состояния:
ничего не обрабатываем
уже обрабатываем такую-то последовательность символов
так что-то он совсем простой - фактически на два состояния:
ничего не обрабатываем
уже обрабатываем такую-то последовательность символов
хм. Надо будет почитать про это. Только меня сомнения берут, что в .net можно сделать строку с такими "читерскими" символами
> ИМХО это лучший и наибыстрейший вариант.
имхо, быстрее будет решить задачу честно.
имхо, быстрее будет решить задачу честно.
кстати в следующем случае:
вход: bacd
правила: aсd -> x; ba -> y
что хотим получить?
bx или ycd?
вход: bacd
правила: aсd -> x; ba -> y
что хотим получить?
bx или ycd?
они не читерские.
а что .net только базовый юникод держит?
все символы ровно два байта?
а что .net только базовый юникод держит?
все символы ровно два байта?
вот я сейчас и разбираюсь с этим вопросом 
upd. Да, на символ - два байта. Если хочется использовать боле 65k символов, используется суррогатная пара, где первый байт из диапазона [08000, 0fff]. Так же делается в UTF-16. Но это, разумеется, геморрой и поддержка этой возможности фактически на пользователе

upd. Да, на символ - два байта. Если хочется использовать боле 65k символов, используется суррогатная пара, где первый байт из диапазона [08000, 0fff]. Так же делается в UTF-16. Но это, разумеется, геморрой и поддержка этой возможности фактически на пользователе
Пусть надо заменить
x_1 => y_1
x_2 => y_2
...
x_n => y_n
Поиск по регулярному выражению вида
x_1|x_2|...|x_n
и замена по хэш-таблице.
x_1 => y_1
x_2 => y_2
...
x_n => y_n
Поиск по регулярному выражению вида
x_1|x_2|...|x_n
и замена по хэш-таблице.
Оставить комментарий
bleyman
Есть некоторый набор замен вида "подстрока1" -> "подстрока2", причём заранее неизвестный. Хочется применить их тексту не по очереди, а одновременно (то есть чтобы результат первой замены не влиял на вторую (например, "a"->"b", "b" -> "c" должно преобразовать "abc" -> "bcc" (а не "ccc", как если их применить по очереди.Один вариант - разбивать замены на "подстрока1" -> guid, guid -> "подстрока2", и надеятся, что такого гуида в тексте/заменах не попадётся (можно даже проверить).
Или можно вместо Regex.Replace получить все позиции нужных слов, запомнить их, а потом заменить ручками.
А как-нибудь прям сразу, за один проход нельзя?