Menu
Traverser une liste de valeurs optionnelles en Scala, Kotlin et Java

Traverser une liste de valeurs optionnelles en Scala, Kotlin et Java

Par Loïc DESCOTTE

13.09.2022

Aujourd’hui nous vous proposons d’étudier un problème assez simple, qui peut arriver dans la vie de tous les jours d’un développeur.7

Disons que nous avons une liste de valeurs optionnelles. Nous voulons produire une seule valeur à partir de cette liste, si la liste est non vide. Le résultat produit sera donc lui aussi de type Option.

Enfin nous voulons séparer les valeurs (si il y en a au moins 2) avec un caractère de notre choix.

  • Exemple 1 : Avoir List(Some("A"), None, Some("B")) en entrée devrait produire le résultat Some("A,B").
  • Exemple 2 : Avoir List(None) en entrée devrait produire None.

 

En Scala


Nous pouvons utiliser la méthode flip de ZIO-prelude (ou la méthode sequence de Cats) pour transformer une List[Option[String]] en Option[List[String]] .

    val list = List(Some("A"), None, Some("B"))
val flippedList = list.filter(_.isDefined).flip // <- Option(List(A,B))
flippedList.map(_.mkString(",")) // <- Some(A,B)
Note : si nous avions souhaité produire simplement une chaine (qui pourrait être vide), nous aurions pu supprimer le wrapper Option et toutes les valeurs non définies (None) de cette manière :
    val flattenList = List(Some("A"), None, Some("B")).flatten // <- List(A, B)
flattenList.mkString(",")

 

En Kotlin

En Kotlin, nous utilisons en général les types nullables en remplacement des options :
    val list = listOf("a", null, "b")
val result = list.filterNotNull().joinToString(separator=",").ifBlank { null }

 

En Java

En Java nous allons utiliser l’API Stream, le résultat est un peu plus verbeux, mais tout de même satisfaisant.Stream::flatMap nous permet de supprimer tous les éléments non définis, et de retirer le wrapper Optional (comme flatten en Scala).
    List<Optional<String>> list = List.of(Optional.of("A"), Optional.empty(), Optional.of("B"));     
var result = Optional.of(
         list.stream()
        .flatMap(Optional::stream)
        .collect(Collectors.joining( "," ))
).filter(Predicate.not(String::isEmpty));

Retour aux articles

C'est à lire...