Neden boş bir dizedeki "bölme" boş olmayan bir dizi döndürür?


111

Boş bir dizede bölme 1 boyutunda bir dizi döndürür:

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

Bunun boş dizi döndürdüğünü düşünün:

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

Lütfen açıkla :)


5
Ek olarak, dize ayırıcının yalnızca bir örneğini içerdiğinde gözlemlenen davranışla tutarsız görünüyor. Bu durumda sonuç fiilen boş bir dizidir: ",". Split (","). Length == 0
LD.

Yanıtlar:


37

Aynı sebepten dolayı

",test" split ','

ve

",test," split ','

2 boyutunda bir dizi döndürür. İlk eşleşmeden önceki her şey ilk öğe olarak döndürülür.


5
Boş dize bir dizedir, hiçbir şey değildir. (Excel hariç her yerde)
Raphael

5
@Raphael Veya Oracle veri tabanında
Austin

7
@Raphael, başka herhangi bir programlama dilinde "".split("wtf").length0 döndürür. Yalnızca JS'de 1'dir.: /
Andrey Mikhaylov - lolmaus

11
@ DanielC.Sobral Tamam, öyleyse neden "," split ","0 dizisi döndürüyor?
Joan

5
Neden son maçtan sonra her şey geri dönmüyor?
Didier A.

72

Bir turuncuyu sıfır kez bölerseniz, tam olarak bir parçanız olur - turuncu.


8
Ama portakal boş değil (eğer oluies'in kastettiği buysa idk), bu bir portakal. Belki orada olması gereken ama olmayan bir portakalı bölmek, böylece tek bir değeri geri alırsınız: boş bir boşluk xD
Nick Rolando

8
Bu derin bir sohbet.

31
Bu metafor mantıklıdır "orange".split(','), ancak boş dizeleri bölmek için açıkça geçerli değildir. Portakal eksikliğimi sıfır kere bölersem, hala portakalım yok; bunu portakal içermeyen boş bir liste mi, tam olarak bir portakalsız listesi mi, on iki portakal içermeyen bir liste mi, yoksa ne? Neyle sonuçlanacağımız değil, onu nasıl temsil ettiğimiz sorusu.
Matchu

1
Ama var olmayan bir kitabı sayfalarına bölerseniz, hiçbir şey elde edemezsiniz.
SMUsamaShah

49

Java ve Scala split yöntemleri aşağıdaki gibi iki adımda çalışır:

  • İlk olarak, dizeyi sınırlayıcıya göre bölün. Bunun doğal sonucu, dizge sınırlayıcıyı içermiyorsa, yalnızca giriş dizesini içeren bir tekil dizinin döndürülmesidir,
  • İkinci olarak, en sağdaki tüm boş dizeleri kaldırın. ",,,".split(",")Boş dizi döndürmesinin nedeni budur .

Buna göre "".split(",")ikinci adımdan dolayı sonucu boş bir dizi olmalı, değil mi?

Olması gerekiyor. Ne yazık ki, bu yapay olarak tanıtılan bir köşe davası. Ve bu kötü, ama en azından belgelenmiştir içinde java.util.regex.Patternsize belgelerine bakmak için hatırlamıyorsam,:

N == 0 için sonuç n <0 için olduğu gibidir, ancak sondaki boş dizeler döndürülmez. (Girişin kendisinin boş bir dize olduğu durumun yukarıda açıklandığı gibi özel olduğunu ve sınır parametresinin burada geçerli olmadığını unutmayın.)

1.Çözüm: Her zaman ikinci parametre olarak -1 geçirin

Bu yüzden, n == -1neyi başarmak istediğinizi özellikle bilmiyorsanız / boş dizenin programınızın girdi olarak alacağı bir şey olmadığından emin değilseniz, her zaman ikinci parametre olarak geçmenizi tavsiye ederim (bu yukarıdaki ikinci adımı atlayacaktır).

2.Çözüm: Guava Splitter sınıfını kullanın

Halihazırda projenizde Guava kullanıyorsanız, Splitter (dokümantasyon) sınıfını deneyebilirsiniz . Çok zengin bir API'ye sahiptir ve kodunuzun anlaşılmasını çok kolaylaştırır.

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, dokümantasyona atıfta bulunan ve tutarsız olduğuna işaret eden tek cevap budur. Ancak, JavaDoc'umda yorumun vurgulanan kısmını bulamadım.
Yogu

Bunu java.util.regex.Pattern içinde buldum, ancak çoğunlukla gitmiş gibi görünüyor. Yazım sırasında, kesinlikle resmi OpenJDK kaynak ağacında bir javadoc olarak mevcuttu. android.googlesource.com/platform/libcore/+/… Belki bir hata rapor etmeliyiz?
Rok Kralj

Bir hatayı bildirmek iyi bir fikir olabilir - davranış kesinlikle değişmeyecek, ancak en azından belgelenmelidir.
Yogu

@RokKralj Android OpenJDK kitaplığını kullanmadı, bunun yerine Apache Harmony'ye dayanıyordu, bu yüzden belki yanlış yere bakıyorsunuz?
lxgr

1
"".split (",", n)Oracle JDK 8 ile n (-1, 0, 1) için tek elemanlı bir dizi oluşturur. Yalnızca boş olmayan belirteçlerin bir listesini almak iyi olur - tam bir düzenli ifade gerekli olabilir (buna benzer bir şey "[^,\\s]+[^,]*[^,\\s]*").
simon.watts

40

Boş bir dizeyi bölmek, boş dizeyi ilk öğe olarak döndürür. Hedef dizede sınırlayıcı bulunmazsa, boş olsa bile orijinal dizeyi tutan 1 boyutunda bir dizi alırsınız.


2
Yanlış. Bölme, en sağdaki tüm boş dizeleri kaldırır, bu nedenle sonuç boş bir dizi olmalıdır. Cevabımı gör. ",".split(",")boş dizi döndürür.
Rok Kralj

23

"a".split(",")-> "a" bu nedenle "".split(",")->""


6
Yanlış. Bölme, en sağdaki tüm boş dizeleri kaldırır, bu nedenle sonuç boş bir dizi olmalıdır. Cevabımı gör. ",".split(",")boş dizi döndürür.
Rok Kralj

5

Tüm programlama dillerinde boş bir dizenin hala geçerli bir Dize olduğunu biliyorum. Dolayısıyla, herhangi bir sınırlayıcı kullanarak bir bölme yapmak, her zaman bu öğenin boş Dize olduğu tek bir öğe dizisi döndürür. Boş (boş olmayan) bir Dize olsaydı, bu farklı bir sorun olurdu.


Bunun bir kütüphane işlevi olduğunu ve dilin bir parçası olmadığını düşünüyorum. Örneğin, google guava'da boş dizeleri atlayabilirsiniz. > Tekrarlanabilir <String> parçalar = com.google.common.base.Splitter.on (','). OmitEmptyStrings (). Split ("");
oluies

2

Bu splitdavranış, iyi ya da kötü için Java'dan miras alınır ...
Scala, Stringilkelden gelen tanımı geçersiz kılmaz .

Davranışı değiştirmek için bağımsız değişkeni kullanabileceğinizilimit unutmayın :

Limit parametresi, modelin uygulanma sayısını kontrol eder ve bu nedenle sonuçtaki dizinin uzunluğunu etkiler. Sınır n sıfırdan büyükse, model en fazla n - 1 kez uygulanacak, dizinin uzunluğu n'den büyük olmayacak ve dizinin son girişi, son eşleşen sınırlayıcının ötesindeki tüm girdileri içerecektir. Eğer n pozitif değilse, desen mümkün olduğu kadar çok uygulanır ve dizi herhangi bir uzunluğa sahip olabilir. N sıfırsa, desen mümkün olduğu kadar çok uygulanacaktır, dizi herhangi bir uzunluğa sahip olabilir ve sondaki boş dizeler atılacaktır.

yani, limit=-1diğer dillerin (tümü?) davranışını elde etmek için ayarlayabilirsiniz :

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

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

Java davranışının oldukça kafa karıştırıcı olduğu iyi biliniyor gibi görünüyor, ancak:

Yukarıdaki davranış, en az Java 5'ten Java 8'e kadar gözlemlenebilir.

JDK-6559590'da boş bir dizge bölünürken boş bir dizi döndürme davranışı değiştirilmeye çalışıldı . Ancak, çeşitli yerlerde gerilemeye neden olduğu zaman JDK-8028321'de kısa süre sonra geri alındı . Değişiklik onu asla ilk Java 8 sürümünde yapmaz.

Not: Bölme yöntemi başlangıçta Java'da değildi ( 1.0.2'de değil ) ama aslında en az 1.4'ten itibaren var (örneğin bkz. JSR51 yaklaşık 2002). Hala araştırıyorum ...

Belirsiz olan şey, Java'nın ilk etapta neden bunu seçtiğidir (benim şüphem, bunun başlangıçta bir "uç durumda" bir hata / hata olduğu yönündedir), ancak şimdi geri dönülmez bir şekilde dile pişirilmiştir ve öyle kalmıştır .


Bunun soruyu yanıtladığından emin değilim - burada verilen örnek için doğru olsa da, boş dizge durumunda yardımcı olmuyor - "".split(",")yine de gibi tek bir öğe dizisi döndürüyor [""].
DaveyDaveDave

@DaveyDaveDave bu, diğer tüm dillerin beklenen davranışıdır. ",,,," Scala'daki tuhaf / farklı davranıştır ve "" durumundan farklıdır.
Andy Hayden

0

Bir dizeyi bölerken boş dizenin özel bir durumu yoktur. Kullanabilirsin:

Some(str)
  .filter(_ != "")
  .map(_.split(","))
  .getOrElse(Array())
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.