Le code suivant provient du guide de démarrage rapide d’Apache Spark .. Quelqu'un peut-il m'expliquer en quoi consiste la variable "line" et d'où elle provient?
textFile.map(line => line.split(" ").size).reduce((a, b) => if (a > b) a else b)
Aussi, comment une valeur est-elle passée dans a, b?
Lien vers le QSG http://spark.Apache.org/docs/latest/quick-start.html
Tout d’abord, en fonction de votre lien, la textfile
est créée en tant que
val textFile = sc.textFile("README.md")
tel que textfile
est un RDD[String]
, ce qui signifie qu'il s'agit d'un ensemble de données réparti résilient de type String
. L'API d'accès est très similaire à celle des collections Scala habituelles.
map
?Imaginez que vous ayez une liste de String
s et que vous souhaitiez la convertir en une liste de Ints représentant la longueur de chaque chaîne.
val stringlist: List[String] = List("ab", "cde", "f")
val intlist: List[Int] = stringlist.map( x => x.length )
La méthode map
attend une fonction. Une fonction qui va de String => Int
. Avec cette fonction, chaque élément de la liste est transformé. Donc, la valeur de intlist est List( 2, 3, 1 )
Ici, nous avons créé une fonction anonyme à partir de String => Int
. C'est x => x.length
. On peut même écrire la fonction plus explicite comme
stringlist.map( (x: String) => x.length )
Si vous utilisez l'écriture explicite ci-dessus, vous pouvez
val stringLength : (String => Int) = {
x => x.length
}
val intlist = stringlist.map( stringLength )
Donc, ici, il est absolument évident que stringLength est une fonction de String
à Int
.
Remarque : En général, map
est ce qui constitue un soi-disant Functor. Pendant que vous fournissez une fonction de A => B, map
du foncteur (ici Liste) vous permet d’utiliser cette fonction également à partir de List[A] => List[B]
. Ceci s'appelle le levage.
Quelle est la variable "ligne"?
Comme mentionné ci-dessus, line
est le paramètre d'entrée de la fonction line => line.split(" ").size
Plus explicite (line: String) => line.split(" ").size
Exemple: Si line
est "hello world", la fonction renvoie 2.
"hello world"
=> Array("hello", "world") // split
=> 2 // size of Array
Comment une valeur est-elle passée dans a, b?
reduce
attend également une fonction de (A, A) => A
, où A
est le type de votre RDD
. Appelons cette fonction op
.
Qu'est-ce que reduce
. Exemple:
List( 1, 2, 3, 4 ).reduce( (x,y) => x + y )
Step 1 : op( 1, 2 ) will be the first evaluation.
Start with 1, 2, that is
x is 1 and y is 2
Step 2: op( op( 1, 2 ), 3 ) - take the next element 3
Take the next element 3:
x is op(1,2) = 3 and y = 3
Step 3: op( op( op( 1, 2 ), 3 ), 4)
Take the next element 4:
x is op(op(1,2), 3 ) = op( 3,3 ) = 6 and y is 4
Le résultat ici est la somme des éléments de la liste, 10.
Remarque : En général, reduce
calcule
op( op( ... op(x_1, x_2) ..., x_{n-1}), x_n)
Tout d’abord, textfile est un RDD [String], disons
TextFile
"hello Tyth"
"cool example, eh?"
"goodbye"
TextFile.map(line => line.split(" ").size)
2
3
1
TextFile.map(line => line.split(" ").size).reduce((a, b) => if (a > b) a else b)
3
Steps here, recall `(a, b) => if (a > b) a else b)`
- op( op(2, 3), 1) evaluates to op(3, 1), since op(2, 3) = 3
- op( 3, 1 ) = 3
Map
et reduce
sont des méthodes de la classe RDD, dont l'interface est similaire à celle des collections scala.
Ce que vous transmettez aux méthodes map
et reduce
est en fait une fonction anonyme (avec un paramètre dans la carte et deux paramètres dans une réduction). textFile
appelle la fonction fournie pour chaque élément (ligne de texte dans ce contexte) dont il dispose.
Peut-être devriez-vous d'abord lire une introduction à la collection Scala.
Vous pouvez en savoir plus sur l'API de classe RDD ici: https://spark.Apache.org/docs/1.2.1/api/scala/#org.Apache.spark.rdd.RDD
ce que map function fait, il prend la liste des arguments et la mappe à une fonction. Similaire à la fonction map en python, si vous êtes familier.
En outre, le fichier est comme une liste de chaînes. (pas exactement mais c'est comme ça que ça se répète)
Considérons que ceci est votre fichier.
val list_a: List[String] = List("first line", "second line", "last line")
Voyons maintenant comment map function fonctionne.
Nous avons besoin de deux choses, list of values
que nous avons déjà et function
à laquelle nous voulons mapper ces valeurs. considérons une fonction très simple pour comprendre.
val myprint = (arg:String)=>println(arg)
cette fonction prend simplement un seul argument de chaîne et s'imprime sur la console.
myprint("hello world")
hello world
si nous associons cette fonction à votre liste, ça va imprimer toutes les lignes
list_a.map(myprint)
Nous pouvons aussi écrire une fonction anonyme, comme mentionné ci-dessous, qui fait la même chose.
list_a.map(arg=>println(arg))
dans votre cas, line
est la première ligne du fichier. vous pouvez changer le nom de l'argument comme bon vous semble. par exemple, dans l'exemple ci-dessus, si je change arg
en line
cela fonctionnerait sans problème
list_a.map(line=>println(line))