Fractionner sur une chaîne vide renvoie un tableau de taille 1:
scala> "".split(',')
res1: Array[String] = Array("")
Considérez que cela retourne un tableau vide:
scala> ",,,,".split(',')
res2: Array[String] = Array()
S'il vous plaît, expliquez :)
Pour la même raison que
",test" split ','
et
",test," split ','
retournera un tableau de taille 2. Tout ce qui se trouve avant la première correspondance est retourné en tant que premier élément.
Si vous divisez une fois le zéro orange, vous avez exactement une pièce - l’orange.
Fractionner une chaîne vide renvoie la chaîne vide en tant que premier élément. Si aucun délimiteur n'est trouvé dans la chaîne cible, vous obtiendrez un tableau de taille 1 contenant la chaîne d'origine, même si elle est vide.
Les méthodes Java et Scala) fonctionnent en deux étapes, comme suit:
",,,".split(",")
renvoie un tableau vide.Selon cela, le résultat de "".split(",")
devrait être un tableau vide à cause de la deuxième étape, non?
Cela devrait. Malheureusement, il s’agit d’un cas de corner introduit artificiellement. Et c’est mauvais, mais au moins cela est documenté dans Java.util.regex.Pattern
, si vous vous rappelez de consulter la documentation:
Pour n == 0, le résultat est identique à n <0, sauf que les chaînes vides en fin de chaîne ne seront pas renvoyées. (Notez que le cas où l'entrée est en soi une chaîne vide est spécial, comme décrit ci-dessus, et le paramètre limit ne s'y applique pas.)
Donc, je vous conseille de toujours passer n == -1
en tant que deuxième paramètre (cette étape passera à l'étape 2 ci-dessus), à moins que vous ne sachiez exactement ce que vous voulez atteindre/vous êtes certain que la chaîne vide ne sera pas quelque chose que votre programme obtiendrait en entrée.
Si vous utilisez déjà Guava dans votre projet, vous pouvez essayer la classe Splitter (documentation) . Il possède une API très riche et rend votre code très facile à comprendre.
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"
"a".split(",")
-> "a"
donc "".split(",")
-> ""
Dans tous les langages de programmation, je sais qu'une chaîne vide est toujours une chaîne valide. Donc, faire une scission en utilisant n'importe quel délimiteur renverra toujours un seul tableau d'éléments où cet élément est la chaîne vide. S'il s'agissait d'une chaîne nulle (non vide), le problème serait différent.
Ce comportement split
est hérité de Java, pour le meilleur ou pour le pire ...
Scala ne remplace pas la définition de la primitive String
.
Notez que vous pouvez utiliser l'argument limit
pour modifier le comportement :
Le paramètre limit contrôle le nombre d'applications du modèle et affecte donc la longueur du tableau résultant. Si la limite n est supérieure à zéro, le motif sera appliqué au plus n fois - 1 fois, la longueur du tableau ne sera pas supérieure à n et la dernière entrée du tableau contiendra toutes les entrées au-delà du dernier délimiteur mis en correspondance. Si n est non positif, le motif sera appliqué autant de fois que possible et le tableau peut avoir n'importe quelle longueur. Si n est égal à zéro, le modèle sera appliqué autant de fois que possible, le tableau peut avoir n'importe quelle longueur et les chaînes vides suivantes seront ignorées.
c'est-à-dire que vous pouvez régler le limit=-1
pour obtenir le comportement de toutes les autres langues:
@ ",a,,b,,".split(",")
res1: Array[String] = Array("", "a", "", "b")
@ ",a,,b,,".split(",", -1) // limit=-1
res2: Array[String] = Array("", "a", "", "b", "", "")
Il semble bien connu que le comportement de Java) est assez déroutant mais:
Le comportement ci-dessus peut être observé depuis au moins Java 5 à Java 8.
Une tentative de modification du comportement afin de renvoyer un tableau vide lors du fractionnement d'une chaîne vide dans JDK-6559590 . Cependant, il a été rapidement annulé dans JDK-8028321 lorsqu'il a provoqué une régression à divers endroits. La modification ne le fait jamais dans la version initiale Java 8).
Remarque: La méthode de scission n'était pas dans Java depuis le début (c'est ) et non dans 1.0.2 ) mais existe en réalité d’au moins 1,4 (voir par exemple JSR51 vers 2002). Je suis toujours en train d’enquêter sur ...
Ce qui est incertain, c’est pourquoi Java a choisi ceci en premier lieu (je soupçonne qu’il s’agissait à l’origine d’un oubli/bogue dans un "cas Edge")), mais qu’il était désormais irrévocablement intégré au langage et ainsi il reste .
Les chaînes vides n'ont aucun statut particulier lors du fractionnement d'une chaîne. Vous pouvez utiliser:
Some(str)
.filter(_ != "")
.map(_.split(","))
.getOrElse(Array())