web-dev-qa-db-ja.com

空の文字列で「分割」すると空でない配列が返されるのはなぜですか?

空の文字列で分割すると、サイズ1の配列が返されます。

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

これは空の配列を返すと考えてください:

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

説明してください :)

89
oluies

同じ理由で

",test" split ','

そして

",test," split ','

サイズ2の配列を返します。最初の一致の前のすべてが最初の要素として返されます。

32

オレンジをゼロ回分割すると、ちょうど1つのピース、つまりオレンジができます。

63
Sam Stainsby

空の文字列を分割すると、空の文字列が最初の要素として返されます。ターゲット文字列に区切り文字が見つからない場合、元の文字列が空であっても、元の文字列を保持しているサイズ1の配列を取得します。

40
Nick Rolando

JavaおよびScala splitメソッドは、次のような2つのステップで動作します。

  • まず、区切り文字で文字列を分割します。自然な結果として、文字列に区切り文字が含まれていない場合、入力文字列のみを含むシングルトン配列が返されます。
  • 次に、右端の空の文字列をすべて削除します。これが、",,,".split(",")が空の配列を返す理由です。

これによれば、"".split(",")の結果は、2番目のステップのために空の配列になるはずですよね?

そうすべき。残念ながら、これは人為的に導入されたコーナーケースです。そしてそれは悪いことですが、少なくともは文書化されていますJava.util.regex.Patternで、覚えていればドキュメントを見てください:

N == 0の場合、結果はn <0の場合と同じですが、末尾の空の文字列は返されません。 (上で説明したように、入力自体が空の文字列である場合は特別であり、limitパラメータは適用されないことに注意してください。)

解決策1:2番目のパラメーターとして常に-1を渡す

ですから、あなたが達成したいことを明確に知らない限り/空の文字列があなたのプログラムのようなものではないことが確実でない限り、常に2番目のパラメータとしてn == -1を渡すことをお勧めします。入力として取得します。

解決策2:Guava Splitterクラスを使用する

プロジェクトですでにGuavaを使用している場合は、 Splitter(documentation) クラスを試すことができます。非常に豊富な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"
36
Rok Kralj

"a".split(",")-> _"a"_したがって、"".split(",")-> _""_

22
weberjn

すべてのプログラミング言語では、空の文字列が依然として有効な文字列であることを知っています。したがって、区切り文字を使用して分割を行うと、その要素が空の文字列である単一の要素配列が常に返されます。 null(空白ではない)文字列の場合、別の問題になります。

4
brent777

この split の動作は、良くも悪くも、Javaから継承されます...
Scalaは、Stringプリミティブの定義をオーバーライドしません。

limit引数を使用して動作を変更できます

Limitパラメーターは、パターンが適用される回数を制御するため、結果の配列の長さに影響します。制限nがゼロより大きい場合、パターンは最大n-1回適用され、配列の長さはn以下になり、配列の最後のエントリには最後に一致した区切り文字を超えるすべての入力が含まれます。 nが正でない場合、パターンはできるだけ多く適用され、配列の長さは任意です。 nがゼロの場合、パターンはできるだけ多く適用されます。配列の長さは任意で、末尾の空の文字列は破棄されます。

つまり、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-655959 で空の文字列を分割するときに、空の配列を返すように動作を変更しようとしました。ただし、さまざまな場所でリグレッションが発生すると、すぐに JDK-8028321 に戻りました。変更により、最初のJava 8リリースになりません。

注:splitメソッドはJavaの最初からではありません( 1.0.2ではない )ですが、実際にはあります)少なくとも1.4から(例: JSR51 2002年頃)。私はまだ調査中です...

不明なのは、なぜJavaが最初にこれを選んだか(これはもともと「エッジケース」の監視/バグだったのではないかと疑っています)が、今では取り返しのつかないほど言語に焼き付けられているためです- 残り

2
Andy Hayden

空の文字列は、文字列の分割中に特別なステータスを持ちません。以下を使用できます。

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