Collections Scala : tableaux, listes, sets, maps et fonctions d'ordre supérieur

Hiérarchie des collections

En Scala, toutes les collections héritent du trait Iterable. On distingue trois grandes familles : Seq, Set et Map. Chaque famille propose généralement deux versions :

  • Immuables : scala.collection.immutable — toute modification retouren une nouvelle collection.
  • Mutables : scala.collection.mutable — la collection est modifiée en place.

Par défaut, Scala privilégie les collections immuables.

Tableaux

Le type Array est un tableau Java : taille fixe, mais cellules modifiables.

Tableau de taille fixe

object DemoTableaux {
  def main(args: Array[String]): Unit = {
    val scores = new Array[Int](4)
    scores(0) = 15
    scores(1) = 12
    scores(2) = 18

    val initiaux = Array(10, 20, 30, 40)

    println(scores(0))

    for (i <- scores.indices) println(scores(i))
    for (valeur <- initiaux) println(valeur)

    val it = scores.iterator
    while (it.hasNext) println(it.next())

    initiaux.foreach(println)
    println(initiaux.mkString(" ; "))
  }
}

Tableau dynamique

import scala.collection.mutable.ArrayBuffer

object DemoBuffers {
  def main(args: Array[String]): Unit = {
    val dyn = ArrayBuffer[Int]()
    val predef = ArrayBuffer(25, 37, 98)

    dyn += 19
    77 +=: dyn
    dyn.append(36)
    dyn.prepend(52, 34)
    dyn.insert(2, 32, 59)

    dyn.remove(0)
    dyn.remove(1, 2)
    dyn -= 36

    println(dyn)
    println(predef)
  }
}

Conversions

import scala.collection.mutable.ArrayBuffer

val extensible: ArrayBuffer[Int] = ArrayBuffer(23, 56, 98)
val fige: Array[Int] = extensible.toArray
val deNouveauExtensible = fige.toBuffer

Tableaux multidimensionnels

object DemoMatrices {
  def main(args: Array[String]): Unit = {
    val grille = Array.ofDim[Int](2, 3)

    grille(0)(2) = 9
    grille(1)(0) = 7

    for (ligne <- grille; cellule <- ligne) println(cellule)

    for (i <- grille.indices; j <- grille(i).indices) {
      print(grille(i)(j) + "\t")
      if (j == grille(i).length - 1) println()
    }

    grille.foreach(_.foreach(println))
  }
}

Listes

List est une séquence immutable par défaut. ListBuffer offre une version mutable.

Liste immutable

object DemoListes {
  def main(args: Array[String]): Unit = {
    val fruits = "pomme" :: "poire" :: "cerise" :: Nil
    val autres = List("kiwi", "mangue")

    println(fruits(1))
    fruits.foreach(println)

    val avecFin = fruits :+ "orange"
    val avecDebut = "fraise" +: fruits
    val concat = fruits ::: autres
    val egalement = fruits ++ autres

    println(avecFin)
    println(concat)
  }
}

Liste mutable

import scala.collection.mutable.ListBuffer

object DemoListBuffers {
  def main(args: Array[String]): Unit = {
    val lb = ListBuffer[Int]()
    val remplie = ListBuffer(12, 53, 75)

    lb.append(15, 62)
    remplie.prepend(32, 25, 64)
    lb.insert(0, 19)
    lb += 32 += 21
    31 +=: lb

    remplie(2) = 80
    remplie.update(0, 30)

    remplie.remove(2)
    remplie -= 25

    val fusion = lb ++ remplie
    lb ++= remplie

    println(fusion)
    println(lb)
  }
}

Ensembles

Par défaut, Set est immutable, non ordonné et sans doublons.

Set immutable

object DemoSets {
  def main(args: Array[String]): Unit = {
    val s = Set(13, 23, 53, 12, 13, 23, 78)
    println(s)

    val s2 = s + 20
    val s3 = s ++ Set(19, 13, 67, 99)
    val s4 = s - 12

    println(s2)
    println(s3)
    println(s4)
  }
}

Set mutable

import scala.collection.mutable.Set

object DemoSetsMutables {
  def main(args: Array[String]): Unit = {
    val ms = Set(13, 23, 53, 12, 13, 23, 78)
    println(ms)

    ms += 11
    val ajoute = ms.add(20)
    println(ajoute)

    ms -= 13
    val supprime = ms.remove(2)
    println(supprime)

    ms ++= Set(27, 28, 29)

    println(ms)
  }
}

Associations clé/valeur

Map stocke des paires. La version immutable est utilisée par défaut.

Map immutable

object DemoMaps {
  def main(args: Array[String]): Unit = {
    val scores = Map("Alice" -> 12, "Bob" -> 15)
    println(scores)

    scores.foreach(println)
    scores.foreach { case (nom, note) => println(s"$nom => $note") }

    for (nom <- scores.keys) {
      println(s"$nom : ${scores.getOrElse(nom, 0)}")
    }

    println(scores.get("Alice"))
    println(scores.getOrElse("Bob", 0))
    println(scores.getOrElse("Inconnu", -1))
  }
}

Map mutable

import scala.collection.mutable.Map

object DemoMapsMutables {
  def main(args: Array[String]): Unit = {
    val scores = Map("Alice" -> 12, "Bob" -> 15)

    scores.put("Carol", 18)
    scores += ("Dave" -> 10)
    scores -= "Alice"

    scores.update("Bob", 16)

    val complement = Map("Eve" -> 20, "Bob" -> 17)
    scores ++= complement

    println(scores)
  }
}

Tuples

Un tuple regroupe un nombre fixe de valeurs, éventuellement de types différents. L'arité est limitée à 22.

object DemoTuples {
  def main(args: Array[String]): Unit = {
    val infos: (String, Int, Char, Boolean) = ("scala", 100, 'a', true)
    println(infos)

    println(infos._1)
    println(infos._2)
    println(infos.productElement(2))

    for (elem <- infos.productIterator) println(elem)

    val imbrique = (12, 0.5, ("a", "b", 7))
    println(imbrique._3._2)
  }
}

Propriétés et parcours

object DemoOperationsCommunes {
  def main(args: Array[String]): Unit = {
    val seq = List(1, 3, 5, 7, 2, 89, 100)
    val ens = Set(23, 34, 423, 75)

    println(seq.length)
    println(seq.size)
    println(ens.size)

    for (e <- seq) print(e + " ")
    println()

    ens.iterator.foreach(e => print(e + " "))
    println()

    println(seq.contains(23))
    println(seq.mkString(" < "))
  }
}

Collections dérivées

object DemoDerivees {
  def main(args: Array[String]): Unit = {
    val a = List(1, 3, 5, 7, 2, 89, 100)
    val b = List(3, 89, 32, 6, 5, 2)

    println(a.head)
    println(a.tail)
    println(a.init)
    println(a.last)
    println(a.reverse)

    println(a.take(3))
    println(a.takeRight(3))
    println(a.drop(3))
    println(a.dropRight(1))

    println(a.union(b))
    println(a.intersect(b))
    println(a.diff(b))
    println(a.zip(b))

    for (fenetre <- a.sliding(3)) println(fenetre)
    for (pas <- a.sliding(3, 2)) println(pas)
  }
}

Calculs statistiques élémentaires

object DemoCalculsSimples {
  def main(args: Array[String]): Unit = {
    val nombres = List(5, 1, 8, 2, -3, 4)
    val paires = List(("a", 3), ("b", 5), ("c", 9), ("d", 2), ("e", 6))

    println(nombres.sum)
    println(nombres.product)
    println(nombres.max)
    println(nombres.min)

    println(paires.maxBy(_._2))
    println(paires.minBy(_._2))

    println(nombres.sorted)
    println(nombres.sorted(Ordering[Int].reverse))

    println(paires.sortBy(_._2))
    println(paires.sortBy(_._2)(Ordering[Int].reverse))

    println(nombres.sortWith(_ < _))
    println(nombres.sortWith(_ > _))
  }
}

Fonctions d'ordre supérieur

Filter, map, flatMap et groupBy

object DemoFonctionsOrdreSuperieur {
  def main(args: Array[String]): Unit = {
    val entiers = List(1, 2, 3, 4, 5, 6, 7)

    val pairs = entiers.filter(_ % 2 == 0)
    val doubles = entiers.map(_ * 2)

    val imbrique = List(List(1, 2, 3), List(6, 7), List(4, 5))
    val plat = imbrique.flatten

    val phrases = List("bonjour le monde", "scala c est top")
    val mots = phrases.flatMap(_.split(" "))

    val groupes = entiers.groupBy(n => if (n % 2 == 0) "pair" else "impair")

    println(pairs)
    println(doubles)
    println(plat)
    println(mots)
    println(groupes)
  }
}

Réductions et accumulations

object DemoReductions {
  def main(args: Array[String]): Unit = {
    val valeurs = List(1, 2, 3, 4, 5)

    println(valeurs.reduce(_ + _))
    println(valeurs.reduceLeft(_ - _))
    println(valeurs.reduceRight(_ - _))

    println(valeurs.fold(0)(_ + _))
    println(valeurs.foldLeft(10)(_ - _))
    println(valeurs.foldRight(10)(_ - _))
  }
}

Étiquettes: Scala immutable-collections mutable-collections arraybuffer listbuffer

Publié le 16 juillet à 20h29