Обріжте рядок на основі довжини струни


136

Я хочу обрізати рядок, якщо довжина перевищує 10 символів.

Припустимо, якщо довжина рядка дорівнює 12 ( String s="abcdafghijkl"), то нова обрізана рядок буде містити "abcdefgh..".

Як я можу цього досягти?


6
можливий дублікат до перших N символів
Stephen C

FYI, горизонтальне крапки це один символ, а не два чи три повних зупинка символів: ...
Василь Бурк

Відповіді:


262
s = s.substring(0, Math.min(s.length(), 10));

Використання Math.minподібного дозволяє уникнути виключення у випадку, коли рядок вже коротший, ніж 10.


Примітки:

  1. Сказане робить справжню обрізку. Якщо ви дійсно хочете замінити останні три (!) Символи крапками, якщо вони скорочуються, тоді використовуйте Apache Commons StringUtils.abbreviate.

  2. Це може поводитись неправильно 1, якщо ваша рядка містить кодові точки Unicode поза BMP; наприклад, Emojis. Для (складнішого) рішення , яке працює правильно для всіх Unicode кодових точок, см @ sibnick - й рішення .


1 - Кодова точка Unicode, яка не знаходиться на площині 0 (BMP), представлена ​​у параметрі "сурогатної пари" (тобто двох charзначень) String. Ігноруючи це, ми можемо зменшити менше 10 кодових очок або (ще гірше) усікати в середині сурогатної пари. З іншого боку, String.length()це вже не ідеальна міра довжини тексту Unicode, тому обрізка на його основі може бути неправильною.


Замість Math.min чи не можемо ми зробити умовну перевірку та виконати підрядку лише у тому випадку, якщо потрібна строка max? напр .:s = (s.length() > 10) ? s.substring(0,10) : s ;
rram

1
Так, звичайно, можна. Прочитайте інші відповіді щодо інших способів вирішення проблеми!
Stephen C

132

StringUtils.abbreviateз бібліотеки Apache Commons Lang може бути вашим другом:

StringUtils.abbreviate("abcdefg", 6) = "abc..."
StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
StringUtils.abbreviate("abcdefg", 4) = "a..."

Commons Lang3 навіть дозволяє встановити спеціальний рядок як маркер заміни. За допомогою цього ви можете, наприклад, встановити еліпсис з одним символом.

StringUtils.abbreviate("abcdefg", "\u2026", 6) = "abcde…"

5
Це могло бути, але питання ОП не вимагає "еліпсису".
Стівен С

9
@StephenC - Запитання показує 8 символів, а потім 2 крапки, з обмеженням довжини 10, що дуже схоже на еліпсис (всього 2 точки, а не 3). Ймовірно, що багато хто з людей, які знайшли це питання, вважають еліпсис корисним.
ToolmakerSteve

12
... і якщо ви не хочете еліпсису, то StringUtils.left () може вам допомогти.
Супероле

1
FYI, HORIZONTAL ELLIPSIS - це єдиний персонаж, а не три символи ПОВНОГО
Василь Бурк

53

Є функція Apache Commons, StringUtilsяка робить це.

s = StringUtils.left(s, 10)

Якщо символи len недоступні або String є нульовим, String буде повернуто без винятку. Порожня рядок повертається, якщо len від'ємний.

StringUtils.left (null, ) = null
StringUtils.left (
, -ve ) = ""
StringUtils.left ("", *) = ""
StringUtils.left ("abc", 0) = ""
StringUtils.left (" abc ", 2) =" ab "
StringUtils.left (" abc ", 4) =" abc "

StringUtils.Left JavaDocs

Люб’язно: Стів МакКоулі


22

Як завжди, ніхто не піклується про сурогатні пари UTF-16. Подивіться про них: Які найпоширеніші символи Unicode, що не належать до BMP, фактично використовуються? Навіть автори org.apache.commons / commons-lang3

Ви можете побачити різницю між правильним кодом та звичайним кодом у цьому зразку:

public static void main(String[] args) {
    //string with FACE WITH TEARS OF JOY symbol
    String s = "abcdafghi\uD83D\uDE02cdefg";
    int maxWidth = 10;
    System.out.println(s);
    //do not care about UTF-16 surrogate pairs
    System.out.println(s.substring(0, Math.min(s.length(), maxWidth)));
    //correctly process UTF-16 surrogate pairs
    if(s.length()>maxWidth){
        int correctedMaxWidth = (Character.isLowSurrogate(s.charAt(maxWidth)))&&maxWidth>0 ? maxWidth-1 : maxWidth;
        System.out.println(s.substring(0, Math.min(s.length(), correctedMaxWidth)));
    }
}

1
Знайдено помилку в «jira» спільноти Apache: issues.apache.org/jira/browse/LANG-1343
Ryan Quinn

10

s = s.length() > 10 ? s.substring(0, 9) : s;


16
Другий параметр підрядка є ексклюзивним, тому ця відповідь обрізає Рядок до 9 символів.
emulcahy

8

Або ви можете просто скористатися цим методом, якщо у вас немає StringUtils під рукою:

public static String abbreviateString(String input, int maxLength) {
    if (input.length() <= maxLength) 
        return input;
    else 
        return input.substring(0, maxLength-2) + "..";
}

Ваш код не працював для мене. Спробуйте цеSystem.out.println(abbreviateString("ABC\ud83d\udc3bDEF", 6));
T3rm1

4

Про всяк випадок, коли ви шукаєте спосіб обрізати та зберегти ОСТАННІ 10 символів рядка.

s = s.substring(Math.max(s.length(),10) - 10);


1

тл; д-р

Ви, здається, запитуєте символ еліпсису ( ) в останньому місці під час обрізання. Ось однолінійний маніпулятор для введення рядка.

String input = "abcdefghijkl";
String output = ( input.length () > 10 ) ? input.substring ( 0 , 10 - 1 ).concat ( "…" ) : input;

Дивіться цей код, який працює на веб-сайті IdeOne.com.

abcdefghi…

Термінальний оператор

Ми можемо зробити однолінійний, використовуючи потрійний оператор .

String input = "abcdefghijkl" ;

String output = 
    ( input.length() > 10 )          // If too long…
    ?                                
    input     
    .substring( 0 , 10 - 1 )         // Take just the first part, adjusting by 1 to replace that last character with an ellipsis.
    .concat( "…" )                   // Add the ellipsis character.
    :                                // Or, if not too long…
    input                            // Just return original string.
;

Дивіться цей код, який працює на веб-сайті IdeOne.com.

abcdefghi…

Потоки Java

Засіб Java Streams робить це цікавим, як для Java 9 та новіших версій. Цікавий, але, можливо, не найкращий підхід.

Ми використовуємо кодові точки, а не charзначення. charТип спадок, і обмежується підмножина всіх можливих Unicode символів.

String input = "abcdefghijkl" ;
int limit = 10 ;
String output =
        input
                .codePoints()
                .limit( limit )
                .collect(                                    // Collect the results of processing each code point.
                        StringBuilder::new,                  // Supplier<R> supplier
                        StringBuilder::appendCodePoint,      // ObjIntConsumer<R> accumulator
                        StringBuilder::append                // BiConsumer<R,​R> combiner
                )
                .toString()
        ;

Якщо у нас були усічені зайві символи, замініть останній символ еліпсісом .

if ( input.length () > limit )
{
    output = output.substring ( 0 , output.length () - 1 ) + "…";
}

Якби тільки я міг придумати спосіб зібрати рядок потоку з частиною "якщо перевищити ліміт, зробіть еліпсис".


Ні. Зрозуміло, він хоче обрізати довжину струни, якщо вона досягає довжини 11 або більше. Ви повинні працювати над новою системою AI
oO

1
@ JD333 Ваш коментар уникає мене. Обрізання довжиною до 10, включаючи еліпсис, саме те, що я показую тут.
Василь Бурк

0
str==null ? str : str.substring(0, Math.min(str.length(), 10))

або,

str==null ? "" : str.substring(0, Math.min(str.length(), 10))

Працює з null.

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