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


111

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

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

これが空の配列を返すことを考慮してください:

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

説明してください :)


5
さらに、文字列にセパレーターのインスタンスが1つだけ含まれている場合に観察される動作と一致しないようです。この場合、結果は実質的に空の配列になります: "、"。split( "、")。length == 0
LD。

回答:


37

同じ理由で

",test" split ','

そして

",test," split ','

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


5
空の文字列は文字列であり、何もではありません。(Excel以外の任意の場所)
ラファエル

5
@RaphaelまたはOracleデータベース
オースティン

7
@Raphael、他のプログラミング言語で"".split("wtf").lengthは0を返します。JSでは1のみです。:/
Andrey Mikhaylov-lolmaus

11
@ DanielC.Sobral OK、それではなぜ"," split ","0の配列を返すのですか?
ジョーン

5
前回の試合後のすべてが返されないのはなぜですか?
Didier A.

72

オレンジを0回に分割すると、オレンジが1つになります。


8
しかし、オレンジは空ではありません(それがoluiesの意味する場合はidkです)。これはオレンジです。あるはずのオレンジではないオレンジを分割するので、1つの値が返されます。空のスペースxD
Nick Rolando

8
これは深い会話です。

31
このメタファーはにとって意味"orange".split(',')がありますが、空の文字列の分割には明らかに関係ありません。オレンジ不足をゼロ回に分けても、オレンジはまだありません。私たちはそれをオレンジ色の空のリスト、ちょうど1つのオレンジ色のリスト、12個のオレンジ色のリスト、または何として表現しますか?それは私たちが最終的に何になるのかではなく、それをどのように表現するかという問題ではありません。
Matchu 2014年

1
しかし、存在しない本をそのページで分割すると、何も得られません。
SMUsamaShah

49

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

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

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

そうすべき。残念ながら、これは人為的に導入されたコーナーケースです。そして、それは悪いことですが、少なくともドキュメントに記載されているjava.util.regex.Patternので、ドキュメントを確認することを忘れないでください。

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

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

したがって、n == -1具体的に何を実現したいのかがわかっていなければ、常に2番目のパラメーターとして渡すことをお勧めします(これにより、上記のステップ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 2016

1
"".split (",", n)Oracle JDK 8を使用して、nの(-1、0、1)の1要素の配列を生成します。空でないトークンのみのリストを取得すると便利です。完全な正規表現が必要な場合があります(など"[^,\\s]+[^,]*[^,\\s]*")。
simon.watts 2018

40

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


2
違う。Splitは、右端の空の文字列をすべて削除するため、結果は空の配列になります。私の答えを見てください。 ",".split(",")空の配列を返します。
Rok Kralj

23

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


6
違う。Splitは、右端の空の文字列をすべて削除するため、結果は空の配列になります。私の答えを見てください。 ",".split(",")空の配列を返します。
Rok Kralj

5

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


これはライブラリ関数であり、言語の一部ではないと思います。たとえばグーグルグアバでは、空の文字列を省略できます。> Iterable <String>個= com.google.common.base.Splitter.on( '、')。omitEmptyStrings()。split( "");
oluies

2

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

注:splitメソッドは最初からJava にはありませんでしたが(1.0.2にはありません)、実際には少なくとも1.4から存在しています(たとえば、2002年頃のJSR51を参照)。まだ調査中です...

どのような不明瞭なのは、Javaが最初の場所でこれを選んだ理由(私の疑いが、それは元々 「エッジケース」で監督/バグだったということです)ですが、今取消不能の言語にとて焼き、それが残っています


これが質問に答えているかどうかはわかりません-ここに示した例では正しいかもしれませんが、空の文字列の場合は役に立ちません-の"".split(",")ような単一の要素配列を返します[""]
DaveyDaveDave

@DaveyDaveDaveこれは、他のすべての言語の予想される動作です。",,,,"はScalaでの奇妙で異なる動作であり、 ""の場合とは異なります。
アンディヘイデン

0

空の文字列は、文字列の分割中は特別なステータスはありません。次のものを使用できます。

Some(str)
  .filter(_ != "")
  .map(_.split(","))
  .getOrElse(Array())
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.