Подтвердить что ты не робот

Является ли более-менее эффективным выполнение проверки перед выполнением замены на С#?

Это почти академический вопрос, но мне любопытно ответить на него.

Предположим, что у вас есть цикл, который выполняет обычную замену в каждой строке в наборе данных. Скажем, там 10 000 таких строк.

Насколько эффективнее иметь что-то вроде этого:

 Row = Row.Replace('X', 'Y');

Или проверить, содержит ли строка даже символ, который должен быть заменен в первую очередь, например:

 if (Row.Contains('X')) Row = Row.Replace('X', 'Y');

Есть ли разница в эффективности? Я понимаю, что разница может быть очень незначительной. Мне интересно узнать, лучше ли один из способов, чем другой, независимо от того, насколько это лучше. Кроме того, будет ли ваш ответ отличаться, если вероятность найти персонажа, который будет заменен, составляет 10% от него, что составляет 90%?

4b9b3361

Ответ 1

Для вашей проверки Row.Contains('X'), является функцией O (n), что означает, что она выполняет итерацию по всей строке по одному символу за раз, чтобы увидеть, существует ли этот символ.

Row.Replace('X', 'Y') работает точно так же, он проверяет каждый символ на один символ за раз.

Итак, если у вас есть эта проверка на месте, вы повторяете строку в два раза подряд. Если вы просто замените, вы перебираете строку последовательно.

Ответ 2

Вам нужно сначала измерить реалистичный набор данных, а затем решить, какая из них выше. Если ваш типичный набор данных не имеет ничего общего, то вызов Contains() может быть более быстрым (потому что хотя Replace также выполняет итерацию по всем символам в строке, будет создан дополнительный строковый объект и сбор мусора из-за неизменность строк), но если "Х" часто присутствует, проверка становится пустой тратой и фактически замедляет работу.

Кроме того, это, как правило, не первое, что нужно искать и беспокоиться о проблемах с производительностью. Такие вещи, как chatty-интерфейсы, сетевые операции ввода-вывода, веб-сервисы, базы данных, обновления файлов ввода-вывода и GUI, будут наносить ущерб вам на порядок больше, чем такие вещи.

Если вы собираетесь делать такие вещи, и если Row вернулся из базы данных (как подсказывает ее название), то получение базы данных для выполнения запроса может быть другим методом экономии производительности. Например.

select MyTextColumn from MyTable where MyTextColumn like '%X%'

Затем выполните замену по всем результатам, потому что вы знаете, что только вернули результаты, в которых необходима замена.

Это вызывает другие проблемы, хотя, например, в SQL Server, если приведенный выше пример включал индекс в MyTextColumn, SQL Server не сможет использовать этот индекс, потому что аргумент like начинается с шаблона (это не считается "приемлемым" ).

В общем, сначала напишите для правильности, читаемости и обслуживания, затем оцените производительность и сделайте целенаправленные улучшения там, где они считаются необходимыми.

Ответ 3

Первый вариант выполняется быстрее. Чтобы проверить, присутствует ли подстрока, сначала ее нужно найти. Поскольку механизм кэширования не будет, почему бы не заменить его напрямую? В противном случае вы будете искать дважды. Если "X" присутствует много раз, вы в основном удваиваете усилие.

Ответ 4

Не забывайте, что строки в С# являются IMMUTABLE. Это означает, что они не могут измениться.

Чтобы заменить что-либо, ему нужно создать новую строку в памяти и скопировать данные через, а затем мусор собрать старую строку позже.

Использование Contains() сначала предотвратит ненужное создание, копирование и сбор мусора строковых данных и, следовательно, будет работать быстрее.