크기를 확인하거나 범위를 벗어나지 않고 문자열의 처음 n자를 얻으려면 어떻게합니까?


163

먼저 n크기 검사를 수행하지 않고 (인라인이 허용 가능) 또는 위험을 감수하지 않고 Java에서 문자열 의 첫 문자 를 어떻게 확인 IndexOutOfBoundsException합니까?


1
예외를 포착하지 않으면 문자 길이가 문자열 길이보다 큰 경우를 처리하는 방법을 모르겠습니다.
Matt Boehm

2
왜? 길이를 확인하거나 예외를 잡는 것에 대한 혐오는 무엇입니까?
paxdiablo

1
호기심이 많지만 왜 크기 검사를 피하고 싶습니까? 이것은 C가 아닙니다.
Tom Hawtin-tackline

내가 표현하고자하는 것은 실제로 길이를 확인하는 것에 대한 혐오가 아닌 if / else 블록을 피하려는 욕구였습니다.
antony.trupe

답변:


347

깔끔한 해결책은 다음과 같습니다.

String upToNCharacters = s.substring(0, Math.min(s.length(), n));

의견 :이 솔루션은 "신선한"반면, / 를 명백한 방식으로 사용하는 솔루션보다 실제로 읽기 쉽지 않다고 생각합니다 . 독자가이 트릭을 보지 못했다 면 코드를 이해 하기더 어려워 야 합니다. IMO, 코드의 의미는 / 버전 에서 더 분명합니다 . 더 깨끗하고 읽기 쉬운 솔루션은 @paxdiablo의 답변을 참조하십시오.ifelseifelse


1
+1. paxdiablo의 답변과 같이 safe_substring 또는 substring_safe라는 함수에 래핑되어 있으면 사용법을 더 쉽게 읽고 의도적으로 알 수 있습니다.
ToolmakerSteve

나는 당신이 말하는 것에 동의하지 않습니다. 이것이 함수에 싸여 있으면 함수 내부의 내용은 중요하지 않으며 명확성 부족으로 인해 "neatness"가 확실히 중요 합니다. 이 솔루션의 요점은 랩퍼 함수를 ​​작성 하지 않으려 는 경우에는 "정확한"것입니다 .
Stephen C

88

바퀴를 재발 명하지 마십시오 ... :

org.apache.commons.lang.StringUtils.substring(String s, int start, int len)

자바 독 은 말한다 :

StringUtils.substring(null, *, *)    = null
StringUtils.substring("", * ,  *)    = "";
StringUtils.substring("abc", 0, 2)   = "ab"
StringUtils.substring("abc", 2, 0)   = ""
StringUtils.substring("abc", 2, 4)   = "c"
StringUtils.substring("abc", 4, 6)   = ""
StringUtils.substring("abc", 2, 2)   = ""
StringUtils.substring("abc", -2, -1) = "b"
StringUtils.substring("abc", -4, 2)  = "ab"

그러므로:

StringUtils.substring("abc", 0, 4) = "abc"

1
그것은 질문에 대답하지 않지만 여전히 그것이 해결책을 제공합니다. OP가 이해할 수 있다면 이것이 더 나은 해결책이라고 생각합니다.
aullah

5
StringUtils.substring(yourString, 0, n)와 같지 않은 것을 지적하는 것도 유용 할 수 있습니다 yourString.substring(0, n). 전자는 from StringUtils이고, 후자는 사용합니다 String.substring(종료 인덱스가 문자열 길이를 초과하면 예외가 발생합니다).
ToolmakerSteve

참고로이 방법의 소스를 살펴보면 끝을 길이로 변경하여 끝이 길이보다 큰 경우를 처리 할 수 ​​있습니다.if (end > str.length()) { end = str.length();}
bholl

1
의 마지막 매개 변수 StringUtils.substring(String s, int start, int len)는 len이 아니며 끝 인덱스입니다.
gorootde

StringUtils.substring ( "abc", 0, 4) = "abc"는 나를 위해 일했습니다. 감사 !
Akash5288

42

Apache Commons Lang 에는이를위한 StringUtils.left방법이 있습니다.

String upToNCharacters = StringUtils.left(s, n);

이것이 최선의 해결책이 아니어야합니까? 왜 그렇게 많이 투표하지 않습니까?
Do Will

3
다른 사람들이 당신과 같은 의견을 가지고 있지 않기 때문에? :-)
Stephen C

이 답변은 원래 질문 날짜보다 훨씬 늦게 나왔습니다.
Mulki

@DoWill : 실행 가능한 환경에 다른 타사 라이브러리를 추가하는 것이 항상 가치가있는 것은 아닙니다.
LarsH

12

SO에 대한 질문의 클래스가 때로는 완벽하게 이해되지 않습니다. 이것은 위험에 가깝습니다 :-)

아마도 배제한 두 가지 방법 중 하나를 사용하여 혐오감을 설명 할 수있을 것입니다.

if명령문이나 예외 잡기 코드로 코드를 작성 하지 않으려는 이유 중 하나는 다음과 같은 도우미 함수를 사용하는 것입니다.

static String substring_safe (String s, int start, int len) { ... }

미리 길이를 확인하고 그에 따라 행동합니다 (작은 줄이나 공백이있는 패드를 반환합니다).

그런 다음 코드에서 전혀 걱정할 필요가 없습니다.

String s2 = substring_safe (s, 10, 7);

대신에:

String s2 = s.substring (10,7);

이것은 많은 문자열 작성 작업을 수행 할 때 코드 흐름을 깨뜨리지 않고 (다른 답변에 대한 귀하의 의견을 바탕으로) 걱정되는 것처럼 작동합니다.


1
@antony, 특히 스마일리 댓글을 더 자세히 읽어야하며 도움을주는 사람들에 대해 그렇게 귀중하지 않아야합니다. 나는 왜 두 가지 방법을 피해야하는지에 대한 근거를 제시하지 않았다고 말하고있었습니다. 그리고 이것은 도우미 기능을 사용하는 진정한 대답이므로 주석에없는 이유입니다.
paxdiablo

1
+1 : OP가 코드를 어지럽히 지 않으려는 요구를 감안할 때 이는 허용되는 것보다 훨씬 나은 접근 방법입니다. (또는 이미 원하는대로 작동하는 기능이있는 라이브러리를 포함하는 Nickkk의 솔루션을 참조하십시오.)
ToolmakerSteve

12
String upToNCharacters = String.format("%."+ n +"s", str);

if n가 변수 인 경우 에는 끔찍 하지만 (따라서 형식 문자열을 구성해야 함) 상수 인 경우에는 분명합니다.

String upToNCharacters = String.format("%.10s", str);

문서


흥미로운 대안은 4 년 전에 제공된 더 전통적인 접근 방식을 사용하여 그것을 사용하는 것을 상상할 수는 없지만.
ToolmakerSteve

입력 문자열은 한 번만 읽으므로 변수에 저장할 필요가 없으므로 깔끔하게 삽입 할 수 있습니다.
Profiterole

3

다음과 같이 부분 문자열 방법을 사용하십시오.

int n = 8;
String s = "Hello, World!";
System.out.println(s.substring(0,n);

n이 문자열의 길이보다 크면 한 주석 작성자가 지적한 것처럼 예외가 발생합니다. 하나 개의 간단한 솔루션은 상태에서이 모든 것을 래핑하는 것입니다 if(s.length()<n)귀하의 else절, 당신은 단지 / 인쇄 전체 문자열을 반환하거나 다른 방법을 처리할지 여부를 선택할 수 있습니다.


1
이 IndexOutOfBoundsException가 점점 위험
antony.trupe

그런데 Java로 프로그래밍 할 계획이라면 String에 대한 대부분의 API 메소드 ( java.sun.com/j2se/1.5.0/docs/api/java/lang/String.html ) 를 암기해야합니다 .
Matt Boehm

나는 이미 그 자체로 답이 아닌 부분 문자열을 배제했습니다 .
antony.trupe

크기를 확인하거나 예외를 잡아야합니다. 이러한 상황 중 하나를 수행해도 현재 상황에서 작동하지 않는 이유를 물을 수 있습니까?
Matt Boehm

3
이것이 어떻게 질문에 대한 답입니까? 문제는 먼저 크기 검사를 수행하지 않아도되고 예외를 잡아야하는 방법을 묻지 않았습니다.
ToolmakerSteve

3

Kotlin으로 개발하기에 운이 좋으면 목표를 달성
하는 take데 사용할 수 있습니다 .

val someString = "hello"

someString.take(10) // result is "hello"
someString.take(4) // result is "hell" )))

0

ApacheCommons StringUtils.abbreviate(String str, int maxWidth)는 "..."를 덧붙이고 접미사를 변경할 수있는 옵션이 없습니다. WordUtils.abbreviate(String str, int lower, int upper, String appendToEnd)다음 빈 공간을 찾습니다.

나는 이것을 여기에 남겨 둘 것입니다 :

public static String abbreviate(String s, int maxLength, String appendToEnd) {
    String result = s;
    appendToEnd = appendToEnd == null ? "" : appendToEnd;
    if (maxLength >= appendToEnd.length()) {
        if (s.length()>maxLength) {
            result = s.substring(0, Math.min(s.length(), maxLength - appendToEnd.length())) + appendToEnd;
        }
    } else {
        throw new StringIndexOutOfBoundsException("maxLength can not be smaller than appendToEnd parameter length.");
    }
    return result;
}

1
@ VolkanGüven이 "ApacheCommons는 저를 놀라게했습니다"문장 때문입니다. 나는 거룩한 ApacheCommons 라이브러리를 비난함으로써 죄를지었습니다. 또는 무엇이든 ...
yuceel

0

코 틀린 : (필요한 경우)

var mText = text.substring(0, text.length.coerceAtMost(20))
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.