Эффективный способ заменить символы в строке (Java)? - PullRequest
2 голосов
/ 24 ноября 2011

Я пишу небольшую программу на Java, которая:

  • принимает текст в виде строки
  • занимает 2 массива символов

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

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

Я объясню на примере: допустим, мой текст (строка): «Java - это здорово!»; у меня есть 2 массива (char []): «absm» и «! @ * $».

Желаемый результат - заменить «а» на «!» от 'b' до '@' и т. д. значение полученного текста будет:

"Ява потрясающая!" изменено на -> "j @ v @ i * @ w * o $ e!"

Какой самый эффективный способ сделать это и почему? Я думал о зацикливании текста, но потом обнаружил, что это не так эффективно.

( StringBuilder / Может использоваться класс String)

Ответы [ 6 ]

3 голосов
/ 24 ноября 2011
StringBuilder sb = new StringBuilder(text);
    for(int i = 0; i<text.length(); i ++)
    {
        for (int j = 0; j < firstCharArray.length;j++)
        {
            if (sb.charAt(i) == firstCharArray[j])
            {
                sb.setCharAt(i, secondCharArray[j]);
                break;
            }

        }
    }

Этот способ эффективен, потому что он использует StringBuilder для изменения символов на месте (если вы используете строки, вам придется каждый раз создавать новые, потому что они неизменны.) Также он минимизирует количество проходов, которые вы должны сделать ( 1 проходит через текстовую строку, а n проходит через первый массив, где n = text.length ())

3 голосов
/ 24 ноября 2011

Полагаю, вы ищете StringUtils.replaceEach , по крайней мере, для справки.

1 голос
/ 24 ноября 2011

Для таких мелочей, как этот, поиск по indexOf (), вероятно, будет быстрее, чем карта, при этом «избегая» внутреннего цикла принятого ответа. Конечно, цикл все еще там, внутри String.indexOf (), но он, вероятно, будет оптимизирован для удобства использования JIT-компилятором, потому что он очень интенсивно используется.

static String replaceChars(String source, String from, String to)
{
    StringBuilder dest = new StringBuilder(source);
    for ( int i = 0; i < source.length(); i++ )
    {
        int foundAt = from.indexOf(source.charAt(i));
        if ( foundAt >= 0 )
            dest.setCharAt(i,to.charAt(foundAt));
    }
    return dest.toString();
}

Обновление: Oracle / Sun JIT использует SIMD хотя бы на некоторых процессорах для indexOf (), что делает его еще быстрее, чем можно было бы предположить.

1 голос
/ 24 ноября 2011

Поместите 2 имеющихся у вас массива на карту

Map<Character, Character> //or Map of Strings

, где ключ - "a", "b" и т. Д., А значение - это символ, который вы хотите заменить на - "@"etc ....

Затем просто замените ключи в вашей строке на значения.

1 голос
/ 24 ноября 2011

Насколько эффективным оно должно быть?Вы делаете это для сотен, тысяч, миллионов слов ???

Я не знаю, является ли это наиболее эффективным, но вы можете использовать метод string indexOf() на каждом из ваших возможных токенов, этоскажет вам, есть ли он, и затем вы можете одновременно заменить этот индекс на соответствующий символ из другого массива.

Codewise, что-то вроде (кстати, это наполовину псевдокод):

for(each of first array) {
    int temp = YourString.indexOf(current array field);
    if (temp >=0) {
        replace with other array
    }
}
0 голосов
/ 24 ноября 2011

Поскольку единственный способ узнать, должен ли символ быть заменен, - это проверить его, вам (или любому другому методу утилит) нужно пройтись по всему тексту, символ за другим. Вы никогда не достигнете лучшей сложности, чем O (n) (n - количество символов в тексте).

...