2017-05-27 1 views
1

J'ai une chaîne que je voudrais vérifier si elle est purement faite de lettres et d'espace.Comprendre les ensembles et les séquences en utilisant la vérification de chaîne comme exemple

val str = "my long string to test" 
val purealpha = " abcdefghijklmnopqrstuvwxyz".toSet 

if (str.forall(purestring(_))) println("PURE") else "NOTPURE" 

Le code CONCISE ci-dessus fait le travail. Cependant, si je le lance ainsi:

val str = "my long string to test" 
val purealpha = " abcdefghijklmnopqrstuvwxyz" // not converted toSet 

str.forall(purealpha(_)) // CONCISE code 

Je reçois une erreur (trouvé: Char ... requis: Boolean) et il ne peut fonctionner en utilisant la méthode contient cette façon:

str.forall(purealpha.contains(_)) 

Ma question est comment puis-je utiliser le formulaire CONCISE sans convertir la chaîne en Set. Toutes les suggestions pour avoir ma propre classe String avec la bonne combinaison de méthodes pour activer le bon code; ou peut-être une ou plusieurs fonction (s) pure (s) travaillant sur des chaînes.

C'est juste un exercice amusant que je fais, donc je peux comprendre les détails complexes de diverses méthodes sur les collections (y compris la méthode d'application) et comment écrire un code et des classes concis.

Répondre

1

Une approche légèrement différente est d'utiliser un modèle de regex.

val str = "my long string to test" 
val purealpha = "[ a-z]+" 
str matches purealpha // res0: Boolean = true 
+0

Nice, concis et intuitif. –

1

Si nous regardons le code source, nous pouvons voir que ces deux implémentations font des choses différentes, bien que donnant le même résultat. Lorsque vous le convertissez en Set et en utilisant le forAll, vous appelez finalement la méthode apply pour l'ensemble. Voici comment l'appliquer est appelé explicitement dans votre code, en utilisant également les paramètres nommés dans les fonctions anonymes:

if (str.forall(s => purestring.apply(s))) println("PURE") else "NOTPURE" // first example 
str.forall(s => purealpha.apply(s)) // second example 

Quoi qu'il en soit, nous allons jeter un coup d'oeil au code source pour demander Set (obtenu à partir GenSetLike.scala):

/** Tests if some element is contained in this set. 
    * 
    * This method is equivalent to `contains`. It allows sets to be interpreted as predicates. 
    * @param elem the element to test for membership. 
    * @return `true` if `elem` is contained in this set, `false` otherwise. 
    */ 
    def apply(elem: A): Boolean = this contains elem 

Lorsque vous quittez le String littéral, vous devez appeler spécifiquement le .contains (ce qui est le code source de ce obtenu à partir SeqLike.scala):

/** Tests whether this $coll contains a given value as an element. 
    * $mayNotTerminateInf 
    * 
    * @param elem the element to test. 
    * @return  `true` if this $coll has an element that is equal (as 
    *    determined by `==`) to `elem`, `false` otherwise. 
    */ 
    def contains[A1 >: A](elem: A1): Boolean = exists (_ == elem) 

Comme vous pouvez l'imaginer, faire une demande pour le littéral String ne donnera pas le même résultat que de faire une demande pour un ensemble.

Une suggestion d'avoir plus de concision est d'omettre le (_) entièrement dans le second exemple (inférence de type de compilateur le ramassez):

val str = "my long string to test" 
val purealpha = " abcdefghijklmnopqrstuvwxyz" // not converted toSet 
str.forall(purealpha.contains) 
+0

bon pour connaître les détails du fonctionnement des combinateurs –