Более или менее эффективно выполнить проверку перед выполнением замены в C #? - PullRequest
13 голосов
/ 15 июля 2011

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

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

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

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

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

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

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

Ответы [ 4 ]

10 голосов
/ 15 июля 2011

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

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

Таким образом, если у вас есть эта проверка, вы потенциально можете выполнить итерацию строки дважды.Если вы просто замените, вы перебираете строку один раз.

1 голос
/ 15 июля 2011

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

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

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

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

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

Хотя это вызывает другие проблемы - например, в SQLСервер, если в приведенном выше примере указан индекс на MyTextColumn, SQL Server не сможет использовать этот индекс, поскольку аргумент like начинается с символа подстановки (он не считается «sargable»).

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

0 голосов
/ 21 июля 2011

Не забывайте, что строки в C # НЕИЗМЕННЫ.Это означает, что они не могут измениться.

Для того, чтобы заменить что-либо, необходимо создать новую строку в памяти и скопировать данные, а затем собрать мусор старой строки.() во-первых, предотвратит ненужное создание, копирование и сборку мусора строковых данных и, следовательно, будет работать быстрее.

0 голосов
/ 15 июля 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...