Java String розділив видалені порожні значення


286

Я намагаюся розділити Значення за допомогою роздільника. Але я знаходжу дивовижні результати

String data = "5|6|7||8|9||";
String[] split = data.split("\\|");
System.out.println(split.length);

Я очікую отримати 8 значень. [5,6,7, EMPTY, 8,9, EMPTY, EMPTY] Але я отримую лише 6 значень.

Будь-яка ідея і як виправити. Незалежно від значення EMPTY в будь-якому місці воно має бути в масиві.

Відповіді:


492

split(delimiter)за замовчуванням видаляє трейлінг порожніх рядків з масиву результатів. Щоб вимкнути цей механізм, нам потрібно використовувати перевантажену версію split(delimiter, limit)з limitвстановленим на негативне значення типу

String[] split = data.split("\\|", -1);

Ще трохи подробиць:
split(regex)внутрішньо повертає результат split(regex, 0)та в документації цього методу, який ви можете знайти (наголос мій)

limitПараметр контролює кількість разів застосовується шаблон і , отже , впливає на довжину результуючого масиву.

Якщо межа nстановить більше нуля , то шаблон буде застосований не більше п - 1 раз, довжина масиву буде не більше , ніж п, а останній запис масиву буде містити всі вхідні дані за межами останнього узгодженого роздільник.

Якщо nце не позитивно, шаблон буде застосовуватися якомога більше разів, і масив може мати будь-яку довжину.

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

Виняток :

Варто згадати, що видалення останнього порожнього рядка має сенс лише в тому випадку, якщо такі порожні рядки створюються розділеним механізмом . Тому, "".split(anything)оскільки ми не можемо розділити ""далі, ми отримаємо як [""]масив результатів .
Це трапляється тому, що розкол тут не відбувся, тому, ""незважаючи на те, що він порожній і трелінг, представляє оригінальну рядок, а не порожню рядок, який був створений процесом розщеплення.


2
Ого. що працювало блискуче. але -1 як це все змінює?
Редді

1
можна навіть спробуватиdata.split("\\|", 8)
Subhrajyoti Majumder

23
Не використовуйте, split("\\|", 8)оскільки це обмежує перші вісім жетонів! Якщо ваша строка є змінною, ви повинні використовувати split("\\|", -1)так, щоб вона створювала необмежену кількість токенів і не відкидала порожні лексеми в кінці.
ADTC

2
@Reddy -1 ( або будь-яке від’ємне число насправді, не має значення, яке абсолютне значення ) говорить про метод розділення, щоб зберегти порожні лексеми в кінці. За замовчуванням дорівнює 0, що вказує на спосіб відкинути порожні маркери в кінці масиву.
ADTC

8
Мабуть, багато людей очікували, що збереження слідів порожніх рядків є функцією за замовчуванням split(regex). Вони опинилися тут і з’ясували, що це не так.
Аттіла Таній

32

З документації String.split(String regex):

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

Тому вам доведеться використовувати дві версії аргументу String.split(String regex, int limit)з негативним значенням:

String[] split = data.split("\\|",-1);

Документ:

Якщо межа n перевищує нуль, тоді шаблон буде застосовано не більше n - 1 разів, довжина масиву буде не більше n, а останній запис масиву буде містити весь вхід за межами останнього відповідного роздільника. Якщо n не позитивно, шаблон буде застосовуватися якомога більше разів, і масив може мати будь-яку довжину. Якщо n дорівнює нулю, візерунок буде застосований якомога більше разів, масив може мати будь-яку довжину, а слідні порожні рядки будуть відкинуті.

Це не залишить порожніх елементів, у тому числі й останніх.


4

Від Doc API для String.split () :

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

Перевантажений String.split (regex, int) більше підходить для вашого випадку.


1
Це пояснює поведінку, але не відповідає на питання.
assylias

@assylias додав це до своєї відповіді зараз :)
PermGenError

4

String[] split = data.split("\\|",-1);

Це не є актуальною вимогою за весь час. Недолік вище наведено нижче:

Scenerio 1:
When all data are present:
    String data = "5|6|7||8|9|10|";
    String[] split = data.split("\\|");
    String[] splt = data.split("\\|",-1);
    System.out.println(split.length); //output: 7
    System.out.println(splt.length); //output: 8

Коли дані відсутні:

Scenerio 2: Data Missing
    String data = "5|6|7||8|||";
    String[] split = data.split("\\|");
    String[] splt = data.split("\\|",-1);
    System.out.println(split.length); //output: 5
    System.out.println(splt.length); //output: 8

Реальна вимога - довжина повинна бути 7, хоча відсутні дані. Тому що є такі випадки, як коли мені потрібно вставити в базу даних чи щось інше. Ми можемо досягти цього, використовуючи підхід нижче.

    String data = "5|6|7||8|||";
    String[] split = data.split("\\|");
    String[] splt = data.replaceAll("\\|$","").split("\\|",-1);
    System.out.println(split.length); //output: 5
    System.out.println(splt.length); //output:7

Що я тут зробив - це видалення "|" труби в кінці, а потім розщеплення струни. Якщо у вас є "," як сепаратор, вам потрібно додати ", $" всередину.


1

у вас може бути кілька роздільників, включаючи символи пробілу, коми, крапки з комою тощо, беруть такі, що знаходяться в групі, що повторюється, з [] +, наприклад:

 String[] tokens = "a , b,  ,c; ;d,      ".split( "[,; \t\n\r]+" );

у вас буде 4 жетони - a, b, c, d

перед застосуванням цього розбиття потрібно видалити провідні роздільники у вихідному рядку.

як відповідь на запитання:

String data = "5|6|7||8|9||";
String[] split = data.split("[\\| \t\n\r]+");

пробіли додаються про всяк випадок, якщо вони будуть розділені разом з |

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.