빈 문자열에서 "분할"이 비어 있지 않은 배열을 반환하는 이유는 무엇입니까?


111

빈 문자열로 분할하면 크기 1의 배열이 반환됩니다.

scala> "".split(',')
res1: Array[String] = Array("")

이것이 빈 배열을 반환한다는 것을 고려하십시오.

scala> ",,,,".split(',')
res2: Array[String] = Array()

설명 해주십시오 :)


5
또한 문자열에 구분 기호의 인스턴스가 하나만 포함 된 경우 관찰 된 동작과 일치하지 않는 것 같습니다. 이 경우 결과는 사실상 빈 배열입니다. ",". split ( ","). length == 0
LD.

답변:


37

같은 이유로

",test" split ','

",test," split ','

크기 2의 배열을 반환합니다. 첫 번째 일치 이전의 모든 항목이 첫 번째 요소로 반환됩니다.


5
빈 문자열은 아무것도 아닌 문자열입니다. (Excel 제외)
Raphael

5
@Raphael 또는 Oracle 데이터베이스
Austin

7
@Raphael은 다른 프로그래밍 언어 "".split("wtf").length에서 0을 반환합니다. JS에서만 1입니다. : /
Andrey Mikhaylov-lolmaus

11
@ DanielC.Sobral 좋아, 왜 "," split ","0의 배열을 반환합니까?
Joan

5
마지막 경기 이후 모든 것이 반환되지 않는 이유는 무엇입니까?
Didier A.

72

오렌지를 0 번 분할하면 정확히 한 조각 인 오렌지가 있습니다.


8
그러나 주황색은 비어 있지 않습니다 (오렌지가 의미하는 바라면 idk). 주황색입니다. 아마도 거기에 있어야하지만 그렇지 않은 오렌지를 분할하여 단일 값을 반환 할 수 있습니다. 빈 공간 xD
Nick Rolando

8
이것은 깊은 대화입니다.

31
이 은유는에 대해 의미가 "orange".split(',')있지만 빈 문자열을 분할하는 것과는 관련이 없습니다. 오렌지 부족을 0 번 분할해도 여전히 오렌지가 없습니다. 오렌지가없는 빈 목록, 정확히 한 개의 오렌지가없는 목록, 열두 개의 오렌지가없는 목록, 또는 무엇으로 표현합니까? 그것은 우리가 무엇으로 끝나는 지에 대한 질문이 아니라 그것을 어떻게 표현하는지에 대한 질문입니다.
Matchu

1
그러나 존재하지 않는 책을 페이지별로 분할하면 아무것도 얻지 못합니다.
SMUsamaShah

49

Java 및 Scala 분할 메서드는 다음과 같은 두 단계로 작동합니다.

  • 먼저 구분 기호로 문자열을 분할합니다. 자연스러운 결과는 문자열에 구분 기호가 포함되지 않은 경우 입력 문자열 만 포함하는 단일 배열이 반환됩니다.
  • 둘째, 가장 오른쪽에있는 빈 문자열을 모두 제거합니다. 이것이 ",,,".split(",")빈 배열을 반환 하는 이유 입니다.

이것에 따르면 "".split(",")두 번째 단계 때문에 결과 는 빈 배열이어야합니다.

그래야한다. 불행히도 이것은 인위적으로 도입 된 코너 케이스입니다. 그리고 그것은 나쁘지만 문서java.util.regex.Pattern살펴 보는 것을 기억한다면 적어도 문서화 되어 있습니다.

n == 0의 경우 결과는 n <0과 같지만 후행 빈 문자열이 반환되지 않습니다. (입력 자체가 빈 문자열 인 경우는 위에서 설명한 것처럼 특별하며 제한 매개 변수가 적용되지 않습니다.)

솔루션 1 : 항상 두 번째 매개 변수로 -1을 전달하십시오.

따라서 n == -1달성하려는 내용을 구체적으로 알고 있거나 프로그램이 입력으로 얻을 수있는 빈 문자열이 아니라고 확신하지 않는 한 항상 두 번째 매개 변수로 전달하는 것이 좋습니다 (위의 2 단계를 건너 뜁니다).

해결 방법 2 : Guava Splitter 클래스 사용

프로젝트에서 이미 Guava를 사용하고 있다면 Splitter (문서) 클래스를 사용해 볼 수 있습니다 . 매우 풍부한 API가 있으며 코드를 이해하기 매우 쉽습니다.

Splitter.on(".").split(".a.b.c.") // "", "a", "b", "c", ""
Splitter.on(",").omitEmptyStrings().split("a,,b,,c") // "a", "b", "c"
Splitter.on(CharMatcher.anyOf(",.")).split("a,b.c") // "a", "b", "c"
Splitter.onPattern("=>?").split("a=b=>c") // "a", "b", "c"
Splitter.on(",").limit(2).split("a,b,c") // "a", "b,c"

1
+1, 이것은 실제로 문서를 인용하고 일관성이 없음을 지적하는 유일한 답변입니다. 그러나 JavaDoc에서 주석의 강조 표시된 부분을 찾지 못했습니다.
Yogu

java.util.regex.Pattern에서 찾았지만 대부분 사라진 것 같습니다. 작성 당시에는 공식 OpenJDK 소스 트리에 javadoc으로 분명히 존재했습니다. android.googlesource.com/platform/libcore/+/… 버그를보고해야할까요?
Rok Kralj

버그를보고하는 것이 좋습니다. 동작은 확실히 변경되지 않지만 최소한 문서화되어야합니다.
Yogu

@RokKralj Android는 OpenJDK 라이브러리를 사용하지 않았지만 대신 Apache Harmony를 기반으로 했으므로 잘못된 위치를 찾고 있습니까?
lxgr

1
"".split (",", n)Oracle JDK 8을 사용하여 (-1, 0, 1)의 n에 대해 하나의 요소 배열을 생성합니다. 비어 있지 않은 토큰 목록 만 가져 오는 것이 좋을 것입니다. 전체 정규식이 필요할 수 있습니다 (예 :) "[^,\\s]+[^,]*[^,\\s]*".
simon.watts

40

빈 문자열을 분할하면 빈 문자열이 첫 번째 요소로 반환됩니다. 대상 문자열에 구분 기호가 없으면 비어 있더라도 원래 문자열을 보유하는 크기 1의 배열을 얻습니다.


2
잘못된. Split은 맨 오른쪽의 빈 문자열을 모두 제거하므로 결과는 빈 배열이어야합니다. 내 대답을 참조하십시오. ",".split(",")빈 배열을 반환합니다.
Rok Kralj

23

"a".split(",")-> "a" 따라서 "".split(",")->""


6
잘못된. Split은 맨 오른쪽의 빈 문자열을 모두 제거하므로 결과는 빈 배열이어야합니다. 내 대답을 참조하십시오. ",".split(",")빈 배열을 반환합니다.
Rok Kralj

5

모든 프로그래밍 언어에서 빈 문자열이 여전히 유효한 문자열이라는 것을 알고 있습니다. 따라서 구분 기호를 사용하여 분할하면 해당 요소가 빈 문자열 인 단일 요소 배열이 항상 반환됩니다. null (공백이 아님) 문자열이면 다른 문제가됩니다.


나는 이것이 언어의 일부가 아니라 라이브러리 기능이라고 생각합니다. 예를 들어 Google 구아바에서는 빈 문자열을 생략 할 수 있습니다. > Iterable <String> 조각 = com.google.common.base.Splitter.on ( ','). omitEmptyStrings (). split ( "");
oluies

2

split동작은 좋든 나쁘 든 Java에서 상속됩니다.
스칼라는 String기본 형식 의 정의를 재정의하지 않습니다 .

당신이 할 수있는, 주 사용 limit동작을 수정하기위한 인수를 :

limit 매개 변수는 패턴이 적용되는 횟수를 제어하므로 결과 배열의 길이에 영향을줍니다. 한계 n이 0보다 크면 패턴은 최대 n-1 회 적용되고 배열의 길이는 n보다 크지 않으며 배열의 마지막 항목에는 마지막 일치 구분 기호를 초과하는 모든 입력이 포함됩니다. n이 양수가 아닌 경우 패턴이 가능한 한 많이 적용되고 배열의 길이는 제한되지 않습니다. n이 0이면 패턴이 가능한 한 많이 적용되고 배열은 임의의 길이를 가질 수 있으며 후행 빈 문자열은 삭제됩니다.

즉, limit=-1다른 언어의 동작을 얻기 위해를 설정할 수 있습니다.

@ ",a,,b,,".split(",")
res1: Array[String] = Array("", "a", "", "b")

@ ",a,,b,,".split(",", -1)  // limit=-1
res2: Array[String] = Array("", "a", "", "b", "", "")

Java 동작이 매우 혼란 스럽지만 다음 과 같이 잘 알려진 것 같습니다 .

위의 동작은 최소한 Java 5에서 Java 8까지 관찰 할 수 있습니다.

JDK-6559590 에서 빈 문자열을 분할 할 때 빈 배열을 반환하도록 동작을 변경하려는 시도가 있었습니다 . 그러나 JDK-8028321 에서 여러 곳에서 회귀가 발생하면 곧 되돌려졌습니다 . 변경 사항은 초기 Java 8 릴리스에 적용되지 않습니다.

참고 : split 메소드는 처음부터 Java에 없었지만 ( 1.0.2에 없음 ) 실제로는 1.4 이상에 있습니다 (예 : JSR51 circa 2002 참조 ). 아직 조사 중입니다 ...

분명하지 않은 것은 Java가 처음에 이것을 선택한 이유입니다 (원래 "가장자리 사건"에서 감독 / 버그 였다고 의심합니다).하지만 이제는 그 언어에 돌이킬 수없이 구워 져서 그대로 남아 있습니다 .


이 질문에 대한 대답이 확실하지 않습니다. 여기에 제공된 예제에서는 사실 일 수 있지만 빈 문자열의 경우에는 도움이되지 않습니다. "".split(",")여전히 [""].
DaveyDaveDave

@DaveyDaveDave는 다른 모든 언어의 예상되는 동작입니다. ",,,,"는 Scala에서 기이하고 다른 동작이며 ""케이스와는 다릅니다.
Andy Hayden 19 년

0

빈 문자열은 문자열을 분할하는 동안 특별한 상태가 없습니다. 다음을 사용할 수 있습니다.

Some(str)
  .filter(_ != "")
  .map(_.split(","))
  .getOrElse(Array())
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.