it-source

빈 문자열의 "분할"이 비어 있지 않은 어레이를 반환하는 이유는 무엇입니까?

criticalcode 2023. 2. 2. 21:09
반응형

빈 문자열의 "분할"이 비어 있지 않은 어레이를 반환하는 이유는 무엇입니까?

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

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

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

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

설명해주세요:)

오렌지를 0번 쪼개면 오렌지 한 조각만 남습니다.

Java 및 Scala 분할 방식은 다음과 같은 두 단계로 작동합니다.

  • 먼저 문자열을 구분 기호로 나눕니다.따라서 문자열에 딜리미터가 포함되지 않으면 입력 문자열만 포함된 싱글톤 배열이 반환됩니다.
  • 둘째, 맨 오른쪽에 있는 문자열을 모두 제거합니다.이게 이유야",,,".split(",")빈 배열을 반환합니다.

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

그래야지. 안타깝게도 이것은 인위적으로 도입된 코너 케이스입니다.그것도 나쁘지만 적어도 에 기록되어 있다.java.util.regex.Pattern메뉴얼을 참조해 주세요.

n == 0 의 경우, 결과는 n < 0 이 됩니다.단, 빈 문자열의 후행은 반환되지 않습니다.(입력 자체가 빈 문자열인 경우는 위에서 설명한 바와 같이 특수하며 limit 파라미터는 적용되지 않습니다).

해결책 1: 항상 -1을 두 번째 매개 변수로 전달합니다.

그러니 항상 합격하시길 권합니다.n == -1두 번째 파라미터(위의 스텝2는 건너뛰기)로 지정합니다.구체적으로 무엇을 달성하고 싶은지 모르는 한, 빈 문자열은 프로그램에서 입력으로 얻을 수 있는 것이 아닙니다.

해결책 2: Guava 스플리터 클래스 사용

프로젝트에서 이미 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의 배열을 얻을 수 있습니다.이 배열은 비어 있어도 마찬가지입니다.

같은 이유로

",test" split ','

그리고.

",test," split ','

는 사이즈 2의 배열을 반환합니다.첫 번째 일치 이전의 모든 것이 첫 번째 요소로 반환됩니다.

"a".split(",")->"a"그러므로"".split(",")->""

모든 프로그래밍 언어에서 빈 문자열은 여전히 유효한 문자열입니다.따라서 임의의 딜리미터를 사용하여 분할하면 항상 단일 요소 배열이 반환됩니다. 여기서 요소가 공백 문자열입니다.공백이 아닌 늘 문자열일 경우 다른 문제가 발생합니다.

이 동작은 Java에서 상속됩니다.좋든 나쁘든...
로부터의 정의를 .String원시적인

인수를 사용하여 동작을 변경할 수 있습니다.

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 릴리즈가 되지 않습니다.

주의: 분할 방식은 처음부터 Java(1.0.2에는 없습니다)가 아니라 1.4부터는 실제로 존재합니다(예: JSR51 circa 2002 참조).아직 조사 중인데...

불분명한 것은 Java가 애초에 이것을 선택한 이유(원래는 「엣지 케이스」의 과실이나 버그에 의한 것이 아닌가 하는 의심)입니다만, 현재는 되돌릴 수 없게 언어에 짜넣어져 있기 때문에, 그대로 남아 있습니다.

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

Some(str)
  .filter(_ != "")
  .map(_.split(","))
  .getOrElse(Array())

이 기능을 사용한다.

public static ArrayList<String> split(String body) {
    return new ArrayList<>(Arrays.asList(Optional.ofNullable(body).filter(a->!a.isEmpty()).orElse(",").split(",")));
}

언급URL : https://stackoverflow.com/questions/4964484/why-does-split-on-an-empty-string-return-a-non-empty-array

반응형