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

Android/Java Regex для удаления лишних нулей из подстрок

У меня есть следующая строка в качестве входных данных:

"2.0,3.00,-4.0,0.00,-0.00,0.03,2.01,0.001,-0.03,101"

Конечный вывод будет выглядеть следующим образом:

"2,3,-4,0,0,.03,2.01,.001,-.03,101"

i.e. все начальные и конечные нули будут удалены, а положительные/отрицательные нули будут просто нулевыми.

Мы можем достичь этого, сначала разбив строку, и используя Regex для каждой части. Но мой размер строки больше 10000.
Как мы можем достичь этого, используя Regex?

Edit:

Анализ ответов:

Я проверил все ответы с помощью String "0.00,-0.00,00.00,-00.00,40.00,-40.00,4.0,-4.0,4.01,-4.01,04.01,-04.01,004.04,-004.04,0004.040,-0004.040,101,.40,-.40,0.40,-0.40" и ответ от Wiktor Stribiżew прошел все тестовые примеры. (см. здесь https://regex101.com/r/tS8hE3/9). В большинстве случаев были приняты другие ответы, но не все.

4b9b3361

Ответ 1

Обновленный ответ тестового случая

Используйте следующее регулярное выражение:

String rx = "-?0+\\.(0)+\\b|\\.0+\\b|\\b0+(?=\\.\\d*[1-9])|\\b0+(?=[1-9]\\d*\\.)|(\\.\\d*?)0+\\b";

И замените на $1$2. См. еще одно демо.

Регулярное выражение соответствует нескольким альтернативам и фиксирует некоторые части строки для последующей повторной установки во время замены:

  • -?0+\.(0)+\b - сопоставление необязательного -, сопровождаемого одним или несколькими 0, за которым следует ., а затем фиксирует ровно один 0, но соответствующий одному или нескольким вхождениям (поскольку (...) к этой группе применяются 0 и +); граница слова в конце требует появления символа без слова после последнего сопоставленного 0. При замене мы восстанавливаем 0 с помощью $1 backreference. Таким образом, -00.00 или 00.00 будут заменены на 0.
  • | - или...
  • \.0+\b - точка, следующая за одним или несколькими нулями перед , (поскольку строка разделена запятой).
  • | - или...
  • \b0+(?=\.\d*[1-9]) - граница слова (начало строки или местоположение после ,), за которым следует один или несколько 0, за которыми следуют . + ноль или более цифр, за которыми следует цифра не-0 ( поэтому мы удаляем ведущие нули в целочисленной части, состоящей только из нулей)
  • | - или...
  • \b0+(?=[1-9]\d*\.) - граница слова, за которой следует один или несколько нулей, за которыми следует цифра не 0, перед . (поэтому мы удаляем все ведущие нули из целой части, которая не равна 0).
  • | - или...
  • (\.\d*?)0+\b - захват . + ноль или более цифр, но как можно меньше, вплоть до первого 0, а затем просто совпадение одного или нескольких нулей (до конца строки или ,) (поэтому мы избавляемся от конечных нулей в десятичной части)

Ответ перед обновлением тестовых случаев

Я предлагаю очень простое и короткое регулярное выражение, которое делает то, что вам нужно:

-0+\.(0)+\b|\.0+\b|\b0+(?=\.\d*[1-9])

Замените $1.

Смотрите демонстрацию regex. Short демоверсия IDEONE:

String re = "-0+\\.(0)+\\b|\\.0+\\b|\\b0+(?=\\.\\d*[1-9])"; 
String str = "2.0,3.00,-4.0,0.00,-0.00,0.03,2.01,0.001,-0.03,101,0.001,-0.03";
String expected = "2,3,-4,0,0,.03,2.01,.001,-.03,101,.001,-.03"; 
System.out.println(str.replaceAll(re, "$1").equals(expected)); // TRUE

Пояснение:

  • -0+\.(0)+\b - минус, сопровождаемый одним или несколькими 0 (0+), за которым следует буквальная точка (\.), за которой следует один или несколько нулей (и захват только последнего 0 t241 > ), за которым следует граница слова (местоположение до , в этом контексте)
  • | - или...
  • \.0+\b - буквальная точка (\.), за которой следует один или несколько нулей, за которыми следует граница слова (местоположение до , в этом контексте)
  • | - или...
  • \b0+(?=\.\d*[1-9]) - граница слова (местоположение после , в этом контексте), за которым следует один или несколько нулей, за которыми должна следовать буквальная точка (\.), затем ноль или более цифр, а затем цифра из От 1 до 9 (так что десятичная часть больше, чем 0).

Ответ 2

\.0+$|^(-)?0+(?=\.)

Вы можете попробовать это. Замените на $1.if u получите пустую строку или - после замены замените ее на 0. См. демонстрацию.

https://regex101.com/r/cZ0sD2/7

Если вы хотите использовать полную строку,

-?0*\.0+\b|\.0+(?=,|$)|(?:^|(?<=,))(-)?0+(?=\.)

См. демонстрацию.

https://regex101.com/r/cZ0sD2/16

Ответ 3

UPDATE, чтобы охватить больше случаев, таких как 01., .100, 01.10

(?<=,|^)(?:[0.+-]+(?=0(?:,|\.\B|$))|0+(?=[1-9]))|\.0+\b|\b0+(?=\d*\.\b)|\.\B|(?<=[1-9])0+(?=,|$)

Этот шаблон требует большего отступления, поэтому на большом входе может замедляться. Строка Java:

"(?<=,|^)(?:[0.+-]+(?=0(?:,|\\.\\B|$))|0+(?=[1-9]))|\\.0+\\b|\\b0+(?=\\d*\\.\\b)|\\.\\B|(?<=[1-9])0+(?=,|$)"

В дополнение к предыдущему шаблону это соответствует

  • (?<=,|^)(?:... |0+(?=[1-9])) добавить ведущие нули, предшествующие [1-9]
  • \.0+\b изменен для соответствия периоду с нулями только до границы слова
  • \b0+(?=\d*\.\b) соответствует нулям на границе, если период, предшествующий необязательным цифрам впереди
  • \.\B соответствует периоду, граничащему с границей без слов (например, .,)
  • (?<=[1-9])0+(?=,|$) соответствует завершающим нулям после [1-9]

Демо в regex101 или Regexplanet (нажмите Java)


Ответ перед обновлением
Вы также можете попробовать replaceAll это регулярное выражение с пустым.

(?<=,|^)[0.+-]+(?=0(?:,|$))|\.0+\b|\b0+(?=\.)
  • (?<=,|^)[0.+-]+(?=0(?:,|$)) соответствует всем частям, состоящим только из [0.+-] с хотя бы конечным нулем. Ограничено с помощью поисковых запросов: (?<=,|^) и (?=0(?:,|$))

  • |\.0+\b или сопоставить период, за которым следует один или несколько нулей и граница слов.

  • |\b0+(?=\.) или сопоставить границу, за которой следует один или несколько нулей, если период впереди.

Неоспоримые случаи, такие как 0., 01, 1.10, пока не охвачены этим шаблоном. Как строка Java:

"(?<=,|^)[0.+-]+(?=0(?:,|$))|\\.0+\\b|\\b0+(?=\\.)"

Демо в regex101 или Regexplanet (щелкните Java)

Ответ 4

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

numbers.replaceAll("\\b0*([1-9]*[0-9]+)(\\.[0-9]*[1-9])?\\.?0*\\b", "$1$2");

с вводом:

2.0,3.00, -4.0,0.00, -0.00,0.03,2.01,0.001, -0.03,101,101.1010,0020.00

результат:

2,3, -4,0, -0,0.03,2.01,0.001, -0.03,101,101.101,20

Если вы хотите иметь десятичные числа без ведущего 0, вы можете использовать следующее.

numbers.replaceAll("\\b0*([0-9]+)(\\.[0-9]*[1-9])?\\.?0+\\b|0+(\\.[0-9]+?)0*\\b", "$1$2$3");

с вводом:

2.0,3.00, -4.0,0.00, -0.00,0.03,2.01,0.001, -0.03,101,101.1010,0020.00

результат:

2,3, -4,0, -0,.03,2.01,.001, -. 03,101,101.101,20

Ответ 5

Вы можете сделать это с 2-кратной заменой:

сначала используйте \.0+(?=(,|$)) и замените на ""

, затем используйте (?!(^|,))-0(?=(,|$)) и замените его на "0"

Ответ 6

Можно ли просто заменить? Пример:

str.replaceAll("\.0+,|,0+(?=\.)", ",");

демо

Ответ 7

/(?!-)(?!0)[1-9][0-9]*\.?[0-9]*[1-9](?!0)|(?!-)(?!0)\.?[0-9]*[1-9](?!0)/g