Bases de Données / Databases

Site Web de l'équipe BD du LIP6 / LIP6 DB Web Site

Outils pour utilisateurs

Outils du site


site:enseignement:master:bdle:tmes:tme3-scala

Différences

Ci-dessous, les différences entre deux révisions de la page.

Lien vers cette vue comparative

Les deux révisions précédentes Révision précédente
Prochaine révision
Révision précédente
site:enseignement:master:bdle:tmes:tme3-scala [10/10/2017 18:17]
amine
site:enseignement:master:bdle:tmes:tme3-scala [01/10/2018 12:39] (Version actuelle)
amine
Ligne 1: Ligne 1:
-{{indexmenu_n>​2}}+{{indexmenu_n>​20}}
  
-====== [TME II-1]  Introduction à Scala  ====== +====== [Pré-requis]  Introduction à Scala  ====== 
-**Remarque générale :** Le cours ne peut être //​self-contained//​ --> consulter la documentation en ligne de Spark.+**Remarque générale :** Le cours ne peut être //​self-contained//​ --> consulter la documentation en ligne de [[https://​spark.apache.org/​docs/​2.1.1/​api/​scala/​index.html#​package|Spark]]. 
 +===== Exercice 1 ===== 
 +Cet exercice illustre les différentes structures de contrôle de Scala présentées en cours. Il permet de comprendre 
 +le paradigme fonctionnel : **seules les fonctions //map, reduce, flatten, filter, flatMap// sont autorisées**.
  
-===== Exercice 0 ===== +Lancer le spark-shell ​en mode local ([[spark|voir Doc]]). 
-Cet exercice illustre les différentes structures de contrôle de Scala présentées ​en cours.+Répondre aux questions ci-dessous.
  
 ==== Question 1 ==== ==== Question 1 ====
-Soit une liste de nombres de 1 à 100 construite à l'aide de l'instruction suivante ​+ 
 +  * Définir la fonction //​maxEntiers//​ qui retourne le plus grand des entiers d'une liste fournie en entrée. 
 +  * Définir la fonction //​scEntiers//​ qui calcule la somme des carrés des entiers d'une liste fournie en entrée. 
 +  * Définir la fonction //​moyEntiers//​ qui calcule la moyenne des entiers d'une liste fournie en entrée. 
 + 
 +Tester au fur et à mesure ces fonctions sur listeEntiers construit comme suit :
 <code scala> <code scala>
-val listeEntiers = List.range(1,​101)+val listeEntiers = List.range(1,​11)
 </​code>​ </​code>​
-  * Définir la fonction //​sommeCarrés//​ qui calcule la somme des carrés des entiers d'une liste fournie en entrée. 
-  * Définir la fonction //moyenne// qui calcule la moyenne des entiers d'une liste fournie en entrée. 
-  * Définir la fonction //maximum// qui retourne le plus grand des entiers d'une liste fournie en entrée. 
-  * Appliquer ces fonctions sur listeEntiers. 
  
-<showif isloggedin>​ 
 **Réponse** **Réponse**
-</showif+<code scala
 +def maxEntiers(in:​ List[Int])= in.reduce((a,​b)=>​(if(a>​b)a else b)) 
 +def scEntiers(in:​ List[Int])= in.map(e=>​e*e).reduce((a,​b)=>​(a+b)) 
 +def moyEntiers(in:​ List[Int])={val p = in.map(e=>​(1,​e)).reduce((a,​b)=>​(a._1+b._1,​ a._2+b._2));​ p._2/​p._1} 
 +</​code>​
  
 ==== Question 2 ==== ==== Question 2 ====
Ligne 27: Ligne 33:
 val listeTemp = List("​7,​2010,​04,​27,​75",​ "​12,​2009,​01,​31,​78",​ "​41,​2009,​03,​25,​95",​ "​2,​2008,​04,​28,​76",​ "​7,​2010,​02,​32,​91"​) val listeTemp = List("​7,​2010,​04,​27,​75",​ "​12,​2009,​01,​31,​78",​ "​41,​2009,​03,​25,​95",​ "​2,​2008,​04,​28,​76",​ "​7,​2010,​02,​32,​91"​)
 </​code>​ </​code>​
-Chaque élément représente un enregistrement fictif de températures avec le format (station, année, mois, température,​ code_département)+Chaque élément représente un enregistrement fictif de températures avec le format (station, année, mois, température,​ code_département).
  
-  * Calculer pour chaque ​année le maximum de ses température.  +  * Calculer pour l'année ​2009 le maximum de ses températures
-  * Calculer ​pour chaque année ​la moyenne de ses température.+  * Idem pour la moyenne de ces température. 
 + 
 +Bien entendu, il faudra faire les transformations et les conversions de type nécessaires!
  
-<showif isloggedin>​ 
 **Réponse** **Réponse**
-</showif>+<code scala> 
 +val temp2009 = listeTemp.map(x=>​x.split(","​)).filter(_(1).toInt==2009).map(x=>​x(3).toInt) 
 +maxEntiers(temp2009) 
 +moyEntiers(temp2009) 
 +</code>
  
  
Ligne 40: Ligne 51:
 Soit une liste chaine de caractères construite à l'aide de l'​instruction suivante Soit une liste chaine de caractères construite à l'aide de l'​instruction suivante
 <code scala> <code scala>
-val melange = List("u123,f01,​3,​20171010",​ "u24,f02,​4,​20171009",​ "f01,​lala,​comedie",​ "f02,​loup,​documentaire"​)+val melange = List("1233,100,​3,​20171010",​ "1224,22,​4,​20171009",​ "100,​lala,​comedie",​ "22,​loup,​documentaire"​)
 </​code>​ </​code>​
 Deux types d'​éléments existent : ceux de la forme (userID, movieID, rating, timestamp) et ceux de la forme  Deux types d'​éléments existent : ceux de la forme (userID, movieID, rating, timestamp) et ceux de la forme 
 (movieID, title, genre). (movieID, title, genre).
 +Le domaine des userID est [1000, 2000] et celui des movieID est [0, 100].
  
 Il est demandé de construire à partir de //melange// deux listes distinctes :  Il est demandé de construire à partir de //melange// deux listes distinctes : 
-  * //notes// contenant les éléments de la forme (userID, movieID, rating, timestamp) ​ et dont le type est (String, String, Int, Int) ; +  * //notes// contenant les éléments de la forme (userID, movieID, rating, timestamp) ​ et dont le type est (Int, String, Int, Int) ; 
-  * //films// contenant les éléments de la forme (movieID, title, genre) et dont le type est (String, String, String).+  * //films// contenant les éléments de la forme (movieID, title, genre) et dont le type est (Int, String, String).
  
-**Conseil** Utiliser le pattern matching avec les variables. 
  
-<showif isloggedin>​ 
 **Réponse** **Réponse**
-</showif+<code scala
 +val notes = melange.map(_.split(","​)).filter(_(0).toInt>​=1000).map(x=>​(x(0).toInt,​x(1),​ x(2).toInt, x(3).toInt)) 
 +val films = melange.map(_.split(","​)).filter(_(0).toInt<​=100).map(x=>​(x(0).toInt,​x(1),​ x(2))) 
 +</​code>​
  
 ==== Question 4 ==== ==== Question 4 ====
 +Soit une liste //​personnes//​ contenant des tuples ayant trois attributs décrivant des personnes :
 +  * le premier attribut est le nom de la personne;
 +  * le second attribut est le type de la personne : etudiant (etu), enseignant (ens) ou inconnu (nan);
 +  * la troisième attribut est l'​année d'​inscription (s'il s'agit d'un étudiant) ou les années d'​ancienneté pour
 +les enseignants.
 +
 +<code scala>
 +val personnes = List(("​Joe",​ "​etu",​ 3), ("​Lee",​ "​etu",​ 4), ("​Sara",​ "​ens",​ 10), ("​John",​ "​ens",​ 5), ("​Bill",​ "​nan",​20))
 +</​code>​
 +
 +  - Définir une classe ​ Etu(nom:​String,​ annee:Int) et une classe Ens(nom:​String,​ annee:Int)
 +  - Transformer //​personnes//​ en une liste d'​objets de la classe Etu ou Ens encapsulant les information des tuples
 +en entrée. ​ Par exemple, le tuple ("​Joe",​ "​etu",​ 3) devra être transformé en un objet Etu("​Joe",​ 3).
 +
 +**Attention** Les personnes de type inconnu ne doivent être dans le résultat!
 +
 +**Astuce** Utiliser le pattern matching
 +
 +
 +
 +
 +**Réponse**
 +<code scala>
 +val personnes = List(("​Joe",​ "​etu",​ 3), ("​Lee",​ "​etu",​ 4), ("​Sara",​ "​ens",​ 10), ("​John",​ "​ens",​ 5), ("​Bill",​ "​eng",​20))
 +class Etu(nom:​String,​ annee:​Int){override def toString()="​Etudiant en " +annee+"​ annee"​}
 +class Ens(nom:​String,​ annee:​Int){override def toString()="​Enseignant avec " +annee+"​ annee d'​experience"​}
 +val classes_personnes = personnes.map(x=>​ x match { case(a,"​ens",​b) =>new Ens(a,b); case(a, "​etu",​ b) =>new Etu(a,b); case _=>​None}).filter(_!=None)
 +</​code>​
  
  
-===== Exercice ​1 : Spark =====+===== Exercice ​=====
 Commencer par copier et décompresser dans votre espace de travail le fichier ​ Commencer par copier et décompresser dans votre espace de travail le fichier ​
  
Ligne 94: Ligne 134:
  
  
 +**Réponse**
 +<code scala>
 +//​1. Extraire dans une variable appelée listEnt le 4e champ de chaque élément de data.
 +val q1 = data.map(x=>​x.split("​ "​)).map(x=>​x(3).toDouble)
  
  
-===== Exercice subsidiaire =====+//​2. Construire à partir de q1 une liste contenant les nombres compris strictement entre 1000 et 1300 puis convertir en type entier.
  
-==== Conversion d'un objet List en un objet Map ==== +val q2 q1.filter(x=> x>1000 && x<​1300 ​)map(x=>​x.toInt)
-Expliquer l'​expression +
-<code scala> +
-val = List(("​ALice",​22)("​Bob",​20), ("​Charles",​22)).toMap+
  
-val x = List((22, "​ALice"​),​ (20, "​Bob"​),​ (22, "​Charles"​)).toMap 
  
-</code>+//​. Construire à partir de q2 une liste contenant les multiples de 3 et l’appeler q33. Faire
  
 +val q33 = q2.filter(x=>​x%3==0)
 +val q39 = q2.filter(x=>​x%9==0)
  
-==== Illustration du flatMap ====+//​4. Construire une liste obtenue en divisant par 10 chaque élément de q33.
  
-Expliquer la différence entre les expressions ​map et flatMap suivantes : +val q4 = q33.map(x=>​x/​10)
  
-<code scala> +//5. Construire à partir de q4 un ensemble d’éléments ​(liste sans doublons).
-val x = List(1, 2, 3).map(x => List(x, 10*x, 100*x) +
-val x = List(1, 2, 3).flatMap(x => List(x, 10*x, 100*x))+
  
-val List(List((1,​ 11), (1, 111)), List((2, 22), (2, 222))).map(x => x) +val q5 q4.distinct
-val y = List(List((1,​ 11), (1, 111)), List((2, 22), (2, 222))).flatMap(x => x)+
  
-</​code>​ 
  
-<code scala> +//6. Construire à partir de q2 une liste contenant ses qui sont multiples de 3 et de 9 à la fois. Utiliser impérativement q33 et q39
- val ys = Map("​a"​ -> List(1 -> 11, 1 -> 111), "​b"​ -> List(2 -> 222, 2 -> 22)).flatMap(_._1)   +
-</​code>​+
  
-Attention, le flatMap appliqué sur une Map retourne une Map. Pour garantir l'​unicité de la clé seules la dernière occurence d'une paire (k,v) est conservée. +val q6 q33.intersection(q39)
-<code scala> +
- val ys Map("​a"​ -> List(1 -> 11, 1 -> 111), "​b"​ -> List(2 -> 222, 2 -> 22)).flatMap(_._2) +
-</​code>​+
  
-La fonction passée en paramêtre au flatMap doit retourner une séquence. Ici une chaine de caractère est considérée implicitment comme une séquence de caractères. 
-<code scala> 
-val pers = Array( (1,"​pierre"​),​ (5,"​alice"​),​ (4, "​paul"​)) 
-val v = pers.flatMap(x=>​x._2) 
-val v = pers.flatMap{ case(numéro,​ prénom) =>​prénom) 
  
 +//​7. Construire à partir de q2 une liste contenant ses éléments qui sont multiples de 3 mais pas de 9. Utiliser impérativement q33 et q39. 
 +
 +val q7 = q33.subtract(q39)
 +
 +//​8. Construire à partir de q2 une liste contenant ses  éléments qui sont multiples de 3 ou de 10.
 +
 +val q8 = q33.union(q2.filter(x=>​x%3==0))
 +
 +//​9. Calculer la somme, ​ la moyenne, le minium ainsi que le maximum des éléments de q8. 
 +
 +val q9sum = q8.map(x=>​x.toDouble).reduce(_+_)
 +
 +val q9max = q8.map(x=>​x.toDouble).reduce((x,​y)=>​if (x > y) x else y)
 +
 +val q9min = q8.map(x=>​x.toDouble).reduce((x,​y)=>​if (x < y) x else y)
 +
 +val q9avg = q8.map(x=>​(x,​1)).reduce((x,​y)=>​(x._1+y._1,​x._2+y._2))
 +
 +q9avg._1/​q9avg._2
 </​code>​ </​code>​
  
-==== Composition de Map ====  
-En considérant la variable pers de la question précédente,​ expliquer le résultat des instructions suivantes 
-  * pers.flatMap(x=>​(x._2) map(y=>​y)) 
-  * pers.flatMap(x=>​(x._2) map(y=>​x._1)) 
-  * pers.flatMap(x=>​(x._2) map(y=>​x._2)) 
-et expliquer pourquoi les deux instructions suivantes sont erronées 
-  * pers.flatMap(x=>​(x._1) map(y=>​y)) 
-  * pers.flatMap(x=>​(x._2) map(y=>​y._1))) 
site/enseignement/master/bdle/tmes/tme3-scala.1507652254.txt.gz · Dernière modification: 10/10/2017 18:17 par amine