Видаліть усі рядки знаку з рядка


311

Я можу використовувати це:

String str = "TextX Xto modifyX";
str = str.replace('X','');//that does not work because there is no such character ''

Чи є спосіб видалити всі події характеру Xз рядка на Java?

Я спробував це, і це не те, що я хочу: str.replace('X',' '); //replace with space


3
Ви спробували замінити строки з одним символом?
peter.murray.rust

Відповіді:


523

Спробуйте використовувати перевантаження, яке бере CharSequenceаргументи (наприклад, String), а не char:

str = str.replace("X", "");

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

9
@vsb: Неправда. Обидва аргументи саме цього перевантаження є CharSequence. docs.oracle.com/javase/7/docs/api/java/lang/…
ЛукаХ

Що робити у випадку Xтипу типу char?
КНУ

7
@Kunal: Я думаю, вам потрібно toStringце спочатку. Тож ваш код виглядав би приблизно такstr = str.replace(yourChar.toString(), "");
LukeH

Зверніть увагу, що ви можете використовувати уникнення Unicode, наприклад, не видаляти нехарактерні характеристикиstr = str.replace("\uffff", "");
Jaime Hablutzel

42

Використання

public String replaceAll(String regex, String replacement)

буду працювати.

Використання було б str.replace("X", "");.

Виконання

"Xlakjsdf Xxx".replaceAll("X", "");

повертає:

lakjsdf xx

6
Regex, мабуть, надмірний для цього, якщо ви не обмежуєтеся підтримкою Java 1.4 - оскільки у версії 1.5 є replaceперевантаження, яка потребує простого CharSequence.
ЛукаХ

3
@LukeH, це декомпільоване джерело для String.replace. Він використовує регулярний вираз. Я погоджуюсь, що це виразка відчуває важкість, але це те, що є під кришкою навіть для прийнятої відповіді вище. публічна заміна рядка (CharSequence var1, CharSequence var2) {return Pattern.compile (var1.toString (), 16) .matcher (this) .replaceAll (Matcher.quoteReplacement (var2.toString ())); }
Perry Tew


6
String test = "09-09-2012";
String arr [] = test.split("-");
String ans = "";

for(String t : arr)
    ans+=t;

Це приклад для того, звідки я видалив персонажа - з рядка.


4
Це дуже неефективно, особливо порівняно з прийнятою відповіддю.
Ерік Робертсон

3
Я думаю, що ця відповідь спрацює, але правильна відповідь вона коротша та швидша
evilReiko

2

Мені подобається використовувати RegEx з цього приводу:

str = str.replace(/X/g, '');

де g означає глобальний, тому він пройде через всю вашу рядок і замінить усі X на ''; якщо ви хочете замінити і X, і x, ви просто скажете:

str = str.replace(/X|x/g, '');

(див. мою загадку тут: скрипка )


Я думаю, це може спрацювати, але правильна відповідь виконується швидше і коротше, завжди краще уникати RegEx якомога більше, оскільки це, як відомо, повільніше, ніж інші методи
evilReiko

2

Привіт. Спробуйте цей код нижче

public class RemoveCharacter {

    public static void main(String[] args){
        String str = "MXy nameX iXs farXazX";
        char x = 'X';
        System.out.println(removeChr(str,x));
    }

    public static String removeChr(String str, char x){
        StringBuilder strBuilder = new StringBuilder();
        char[] rmString = str.toCharArray();
        for(int i=0; i<rmString.length; i++){
            if(rmString[i] == x){

            } else {
                strBuilder.append(rmString[i]);
            }
        }
        return strBuilder.toString();
    }
}

як би ви це зробили, якби замість x у нас була ще одна струна? Приємне рішення!
Мона Джалал

2

Використовуйте substituAll замість заміни

str = str.replaceAll("X,"");

Це має дати вам бажану відповідь.


замінити закінчується за допомогою substituAll. Погляньте на реалізацію. Ось як реалізовано String # return Pattern.compile(target.toString(), Pattern.LITERAL).matcher( this).replaceAll(Matcher.quoteReplacement(replacement.toString()));
substitute

0
package com.acn.demo.action;

public class RemoveCharFromString {

    static String input = "";
    public static void main(String[] args) {
        input = "abadbbeb34erterb";
        char token = 'b';
        removeChar(token);
    }

    private static void removeChar(char token) {
        // TODO Auto-generated method stub
        System.out.println(input);
        for (int i=0;i<input.length();i++) {
            if (input.charAt(i) == token) {
            input = input.replace(input.charAt(i), ' ');
                System.out.println("MATCH FOUND");
            }
            input = input.replaceAll(" ", "");
            System.out.println(input);
        }
    }
}

input = "deletes all blanks too";дає "deletesallalllankstoo"
Каплан

0

ось функція лямбда, яка видаляє всі символи, передані як рядки

BiFunction<String,String,String> deleteChars = (fromString, chars) -> {
  StringBuilder buf = new StringBuilder( fromString );
  IntStream.range( 0, buf.length() ).forEach( i -> {
    while( i < buf.length() && chars.indexOf( buf.charAt( i ) ) >= 0 )
      buf.deleteCharAt( i );
  } );
  return( buf.toString() );
};

String str = "TextX XYto modifyZ";
deleteChars.apply( str, "XYZ" ); // –> "Text to modify"

Це рішення враховує, що результуюча рядок - на відміну від replace()- ніколи не стає більшою від початкової рядка при видаленні символів. Таким чином , це дозволяє уникнути повторного виділення і копіювання в той час як додавання символів мудрі в StringBuilderякості replace()робить.
Не кажучи вже про безглузді покоління Patternта Matcherвипадки replace(), які ніколи не потрібні для видалення.
На відміну від replace()цього рішення можна видалити кілька символів одним махом.


Ламбдас / функціональне програмування зараз дуже хіп, але використовувати його для створення рішення, яке на 10 разів довше, ніж обрана відповідь не може бути виправданою IMHO, отже, голосування вниз.
Фолксман

str.replace("…", "")екземпляри, private Pattern(…)а потім на згенерованому шаблоні викликів public String replaceAll(String repl). Тож відбулися такі виклики функцій: return Pattern.compile(target.toString(), Pattern.LITERAL).matcher( this).replaceAll(Matcher.quoteReplacement(replacement.toString())); - дивіться коментар Sal_Vader_808. В цілому приблизно в 3 рази довше , ніж мій хіп лямбда - рішення. І ось тут непогано пояснено, чому рішення мого лямбда- стегна також швидше: Чому Java String :: замінити () так повільно?
Каплан

По суті: Якби мова йшла дійсно про розмір рішення, деякі інші рішення вдвічі більші чи рішення, для яких потрібна зовнішня бібліотека, були б більш підходящими кандидатами для критики. Мовне розширення, яке є частиною мови протягом багатьох років з часу Java 8, насправді не є хіп . Загальна проблема системи балів полягає в тому, що коефіцієнт часу важить більше, ніж якість рішення. Як наслідок, більш сучасні, а іноді і кращі рішення все частіше знаходять у задній третині.
Каплан

Я мав на увазі 10 разів довше з точки зору швидкості виконання коду. Все, що компілює шаблон регулярного виразів кожного разу, коли він викликається, може бути набагато повільніше. Вам дійсно потрібно кешувати зібраний збірник і повторно використовувати його, якщо використовувати такий регулярний вираз на високій частоті (ОП не говорить про те, для якого сценарію він використовується - може бути рідкісним сценарієм очищення даних від подання форми або може бути використаний у стислій формі петлю називають 1000 разів у секунду).
Фолксман

Що стосується проблем ефективності, я додав нову відповідь, яка дає швидкий орієнтир щодо різноманітних наданих відповідей. Якщо ОП робить цю операцію часто, вони повинні уникати параметра String.replace (), оскільки повторна перекомпіляція шаблону регулярних виразів під кришкою дуже дорога.
Volksman

0

Оцінка основних відповідей з показником ефективності, який підтверджує занепокоєння, що поточна обрана відповідь робить дорогими операції з вирівнюванням під кришкою

На сьогодні надані відповіді в трьох основних стилях (ігнорування відповіді на JavaScript;)):

  • Використовуйте String.replace (charsToDelete, ""); який використовує регулярний вираз під кришкою
  • Використовуйте лямбда
  • Використовуйте просту реалізацію Java

Щодо розміру коду чітко, String.replace є найбільш стислим. Проста реалізація Java трохи менша та чистіша (IMHO), ніж Lambda (не помиляйтесь, я використовую Lambdas часто там, де вони підходять)

Швидкість виконання була, для того, щоб найшвидше і повільніше: проста реалізація Java, Lambda, а потім String.replace () (що викликає regex).

На сьогоднішній день найбільш швидкою реалізацією була проста реалізація Java, налаштована таким чином, що вона попередньо розміщує буфер StringBuilder до максимально можливої ​​довжини результату, а потім просто додає символи до буфера, які не знаходяться в рядку "символи для видалення". Це дозволяє уникнути перерозподілу, який відбуватиметься для Strings> 16 символів завдовжки (розподіл за замовчуванням для StringBuilder), а також уникне удару "слайд вліво" про видалення символів з копії рядка, що відбувається, це реалізація Lambda.

У наведеному нижче коді виконується простий тест на орієнтир, запускаючи кожну реалізацію 1 000 000 разів та реєструючи минулий час.

Точні результати залежать від кожного запуску, але порядок виконання ніколи не змінюється:

Start simple Java implementation
Time: 157 ms
Start Lambda implementation
Time: 253 ms
Start String.replace implementation
Time: 634 ms

Реалізація лямбда (скопійована з відповіді Каплана) може бути повільнішою, оскільки вона виконує "зсув на один" усіх символів праворуч від символу, що видаляється. Це, очевидно, погіршиться для довших рядків з великою кількістю символів, які потребують видалення. Крім того, можуть бути деякі накладні витрати в самій реалізації Lambda.

Реалізація String.replace, використовує регулярний вираз і робить регулярний вираз "компілювати" при кожному виклику. Оптимізацією цього було б використання регулярного виразу та кешування складеного шаблону, щоб уникнути витрат на його компіляцію кожного разу.

package com.sample;

import java.util.function.BiFunction;
import java.util.stream.IntStream;

public class Main {

    static public String deleteCharsSimple(String fromString, String charsToDelete)
    {
        StringBuilder buf = new StringBuilder(fromString.length()); // Preallocate to max possible result length
        for(int i = 0; i < fromString.length(); i++)
            if (charsToDelete.indexOf(fromString.charAt(i)) < 0)
                buf.append(fromString.charAt(i));   // char not in chars to delete so add it
        return buf.toString();
    }

    static public String deleteCharsLambda(String fromString1, String charsToDelete)
    {
        BiFunction<String, String, String> deleteChars = (fromString, chars) -> {
            StringBuilder buf = new StringBuilder(fromString);
            IntStream.range(0, buf.length()).forEach(i -> {
                while (i < buf.length() && chars.indexOf(buf.charAt(i)) >= 0)
                    buf.deleteCharAt(i);
            });
            return (buf.toString());
        };

        return deleteChars.apply(fromString1, charsToDelete);
    }

    static public String deleteCharsReplace(String fromString, String charsToDelete)
    {
        return fromString.replace(charsToDelete, "");
    }


    public static void main(String[] args)
    {
        String str = "XXXTextX XXto modifyX";
        String charsToDelete = "X";  // Should only be one char as per OP's requirement

        long start, end;

        System.out.println("Start simple");
        start = System.currentTimeMillis();

        for (int i = 0; i < 1000000; i++)
            deleteCharsSimple(str, charsToDelete);

        end = System.currentTimeMillis();
        System.out.println("Time: " + (end - start));

        System.out.println("Start lambda");
        start = System.currentTimeMillis();
        for (int i = 0; i < 1000000; i++)
            deleteCharsLambda(str, charsToDelete);

        end = System.currentTimeMillis();
        System.out.println("Time: " + (end - start));

        System.out.println("Start replace");
        start = System.currentTimeMillis();

        for (int i = 0; i < 1000000; i++)
            deleteCharsReplace(str, charsToDelete);

        end = System.currentTimeMillis();
        System.out.println("Time: " + (end - start));
    }
}

Якщо лямбда-функція викликається так, як це передбачалося робити, час є наступним (ніхто не ввімкнює функцію лямбда у функцію члена) . Крім того, ваш deleteCharsReplace () неправильно реалізований: він замінює один рядок "XYZ", а не як потрібно "X", "Y" та "Z", що fromString.replace("X", "").replace("Y", "").replace("Z", "");потрібно. Тепер ми отримуємо правильний термін: Почніть простий час: 759 | Час лямбда: 1092 | Почати видаленняCharsLambda () Час: 1420 | Початок заміни виправлений Час: 4636
Каплан

"ніхто не вбудовує лямбда-функцію у функцію-члена" - за винятком цілей виклику її у еталонній ситуації, щоб вона відповідала тому, як викликаються інші реалізації.
Фолксман

Я щойно зрозумів, що ОП запитав про видалення всіх подій одного символу, але ваша відповідь змінила сферу роботи з набором символів. "Прийнята" відповідь реалізація, яку я використовував, не передбачає і ніколи не передбачала задоволення кількох символів. Тому я оновив вищевказаний показник, щоб відобразити це та еталонні часи. BTW, якщо ви хочете збільшити сферу підтримки декількох символів, що вимагають заміни в декілька разів, це дорого. Краще перейти на один виклик, щоб замінитиAll ("[XYZ]", "")
Volksman

Функція, як показано в рішенні , ініціюється лише один раз, коли викликається. Обміняти функцію definiton додатково до виклику функції у функцію-член має єдиний ефект, який спотворює орієнтир.
Каплан

Практично неможливо правильно орієнтувати швидкі методи тривалості, здійснюючи один виклик, оскільки дисперсія кожного виклику настільки велика. Таким чином, бенчмаркінг зазвичай включає багато повторних дзвінків на один і той же метод, а потім оцінюється загальний час для порівняння із загальним часом альтернатив (або для розрахунку середнього, якщо потрібно) ..
Volksman

0

Вам потрібно буде помістити символи, які потрібно видалити всередині квадратних дужок під час заміни. Приклад коду буде таким:

String s = "$116.42".replaceAll("[$]", "");

-3

Ви можете використовувати, str = str.replace("X", "");як було сказано раніше, і вам буде добре. Для вашої інформації ''це не порожній (або дійсний) символ, але '\0'є.

Таким чином, ви можете використовувати str = str.replace('X', '\0');замість цього.


9
це неправильно. '\ 0' видасть фактичний нульовий символ. str.replace ('X', '\ 0') еквівалентно str.replace ("X", "\ u0000"), що зовсім не те, чого хотіла ОП
Андрій
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.