No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Curso de Scala básico

Curso de Scala básico

Carlos Daniel Sanchez

Carlos Daniel Sanchez

Colecciones: Secuencias, Conjuntos y Mapas

10/36
Recursos

Aportes 21

Preguntas 1

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Reto!

object colecciones {
  def main(args: Array[String]): Unit = {
    val lista: Seq[Int] = Seq(1,3,5,7,9,9,11,17,20,20,100)

    medidasT(lista)
  }

  //  funciones

  def media(args: Seq[Int]): Int = {
    val media = (args.sum)/(args.size)
    media
  }

  def mediana(args: Seq[Int]): Int = {
    val indice = (args.size/2)
    args(indice)
  }

  def moda(args: Seq[Int]): Int = {
    args
      .groupBy(x => x)
      .maxBy(x => x._2.size)
      ._1
  }


  // funcion de medidas de tendencia central
  def medidasT(args: Seq[Int]): Unit = {
    val lista = args.sorted
    val mapa = Map(
      "media"   -> media(lista),
      "mediana" -> mediana(lista),
      "moda"    -> moda(lista)
    )


    mapa foreach ( x => println(x._1 + " -> " + x._2) )

  }
}

En la versión actual 2.12, no se dispone de la función appended.
To append or prepend one or more elements to a Vector or Seq, use these methods:

to append one item, use :+
to append multiple items, use ++
to prepend one item, use +:
to prepend multiple items, use ++:

Solución del reto:

def media(numbers: Seq[Int]) = numbers.sum / numbers.size
def mediana(numbers: Seq[Int]) = if(numbers.size % 2 == 1) {
numbers(numbers.size/2)
} else {
val position = numbers.size / 2
(numbers(position) + numbers(position - 1))/ 2
}
def moda(numbers: Seq[Int]) = numbers.groupBy(group => group).maxBy( num => num._2.size)._1

val numbers = Seq(1, 2, 3, 5, 6, 6)

val result: ( Seq[Int] => Map[String, Int] ) = { numbers: Seq[Int] => Map(
(“Media”, media(numbers)), (“Mediana”, mediana(numbers)), (“Moda”, moda(numbers))
)}
println(result( numbers ))

cualquier feedback es bienvenido 😃

Listas

Es el tipo de dato más básico en lenguajes funcionales. A diferencia de las listas en otros lenguajes, aquí por defecto son inmutables

  • List, Seq, Array

Conjuntos

Es muy similar a usar una lista, pero conceptualmente es distinto. Por definición, los elementos en un conjunto no tienen orden, ni pudeden estar repetidos.

  • Set,

Mapas

También se les conoce como diccionarios. No es muy diferente a lo que ya conocemos, solo que también son inmutables por defecto

  • Map

Loops en FP

En programación funcional no usaremos un for o un while como se hace en lenguajes imperativos. Por el contrario, usaremos funciones que recorran los elementos de una lista por nosotros.

  • map()
  • filter()
  • filterNot()
  • forEach()
  • zip()
  • find()
val a1 = Seq(1,2,3
// a1: Seq[Int] = List(1, 2, 3)

a1.appendded

val a2 = a1.appended(4)
// a1: Seq[Int] = List(1, 2, 3, 4)

a1 :+ 4
// res18: Seq[Int] = List(1, 2, 3, 4)

a1.:+(4)
// res19: Seq[Int] = List(1, 2, 3, 4)

a1 appended 4
// res21: Seq[Int] = List(1, 2, 3, 4)

a2(0) // devuelve el valor en la posición 0
// res22: Int = 1

val c1 = Set(1,2,3)
//c1: scala.collection.immutable.Set[Int] = Set(1,2,3)

c1.incl(4)
//res: scala.collection.immutable.Set[Int] = Set(1,2,3,4)

val c2 = c1.incl(4)
//c2: scala.collection.immutable.Set[Int] = Set(1,2,3,4)

c1 + 4
//res: scala.collection.immutable.Set[Int] = Set(1,2,3,4)

c2(4)
// res29: Boolean = true

val m1 = Map(1) // error

val m1 = Map((1,"hola"))
//m1 scala.collection.immutable.Map[Int,String] = Map(1 -> hola)

val m1 = Map(1 -> "hola")
//m1 scala.collection.immutable.Map[Int,String] = Map(1 -> hola)

val m2 = m1 + (2, "hello") //error

val m2 = m1 + (2 -> "hello")
//m1 scala.collection.immutable.Map[Int,String] = Map(1 -> hola, 2 -> "hello")

c2.map(x => x+1)
//res: scala.collection.immutable.Set[Int] = Set(2,3,4,5)

a2.map(x => x+1)
// res19: Seq[Int] = List(2, 3, 4, 5)

m2.view.mapValues(s => s + "!")
//m1 scala.collection.MapView[Int,String] = MapView(<not computed>)

```js import scala.util.Random def getMean(sample: Seq[Int]): (String, Double) = if (sample.isEmpty) { ("mean" -> 0.0) } else { ("mean" -> sample.sum.toDouble / sample.length) } def getMedian(sample: Seq[Int]): (String, Double) = { val sortedSample = sample.sorted val sortedLength = sample.length if (sortedSample.isEmpty) { ("median" -> 0.0) } else if (sortedLength % 2 == 1) { ("median" -> sortedSample(sortedLength/2).toDouble) } else { val middel1 = sortedSample((sortedLength-1)/2) val middel2 = sortedSample(sortedLength/2) val median = (middel1 + middel2).toDouble / 2 ("median" -> median) } } def getMode(sample: Seq[Int]): (String, Double) = { val freqMap = sample.groupBy(identity).view.mapValues(_.size) val maxFreq = freqMap.values.max val mode = freqMap.filter { case (_, freq) => freq == maxFreq }.keys.head ("mode", mode.toDouble) } def getStatistics(sample: Seq[Int]): Map[String, Double] = Map(getMean(sample), getMedian(sample), getMode(sample)) val randomeSample = Seq.fill(100)(Random.nextInt(1000)) val statistics = getStatistics(randomeSample) println(randomeSample) println(statistics) ```

Reto !

  val numbers = List(1,3,5,7,9,9,11,17,20,20,100)

  def mediaMedianaModa(numbers:List[Int]):Unit =
    val media =Math.round(numbers.sum.toDouble / numbers.length)
      val numbersOrder = numbers.sorted
      val mediana = if (numbersOrder.length % 2 == 0) {
        val mitadSuperior = numbersOrder.length / 2
        val mitadInferior = mitadSuperior - 1
        Math.round((numbersOrder(mitadInferior).toDouble + numbersOrder(mitadSuperior).toDouble) / 2)
      } else {
        Math.round(numbersOrder(numbersOrder.length / 2).toDouble)
      }
    val frecuencias = numbers.groupBy(identity).view.mapValues(_.size)
    val maxFrecuencia = frecuencias.values.max
    val moda=frecuencias.filter(_._2 == maxFrecuencia).keys.toList

    println(s"Media:$media, Mediana:$mediana, Moda:${if(moda.size==numbers.size) "no hay moda" else if(moda.size==1)moda(0) else moda} ")

  mediaMedianaModa(numbers)
object calculo {
     |  def media(x:Seq[Int]) = { val l = x.length; val s = x.sum; val result =  s / l; result}
     |  def mediana(x:Seq[Int]) = {val l = x.length; val r = l / 2 ;val result = x(r.round); result}
     |  def getData(x:Seq[Int]) = {val result = Map("Media: " -> media(x), "Mediana: " -> mediana(x)); result}
     | }

Resultado del reto:

package demo

object Demo {
  // Main Method
  def main(args: Array[String]) {

    val nums: List[Int] = List(1, 2, 3, 2, 4, 4, 4)
    val numsOrdered = nums.sorted

    // Media
    val sumaLista = numsOrdered.sum
    val conteoLista = numsOrdered.size

    val mediana = sumaLista/conteoLista
    val media = conteoLista/2
    val moda = numsOrdered.groupBy(identity).maxBy(_._2.size)._1

    println(Map(("mediana",mediana)))
    println(Map(("moda",moda)))
    println(Map(("media",media)))

  }
}


Si queremos hacer una secuencia, lista o colección sin inicializarla pero con los tipos que contendrá definidos podemos usar la siquiente sintaxis.

val a = Seq[Int]()

En ocasiones, queremos declarar una lista vacia que contenga elementos de cierto tipo de dato.

En el siguiente ejemplo se trata de añadir un elemento a una lista vacia y falla.

Sin embargo, al utilizar la sintaxis descrita anteriormente, no tenemos ningún problema.

Este seria el equivalente a los tipos genéricos en otros lenguajes de programación donde se suele utilizar “<>”.

También puede utilizarse:

var a : Seq[Int] = Seq()

Por útlimo, en Scala3 podemos utilizar la siguiente sintaxis si quisieramos hacer una colección que contenga más de un tipo de dato.

Mi solución al reto V2:

// Utils
def getCount(list:Iterable[Int]) = {
  list.fold(0)((item,next)=> item + 1)
}
def getMiddle(list:List[Int]) = {
  val middle = getCount(list).toFloat / 2
  if (middle.isValidInt) {
    (list(middle.toInt - 1),list(middle.toInt))
  }
  else {
    list(middle.floor.toInt)
  }
}
def getFrequency(list:List[Int]) = {
 list.toList.groupMapReduce(identity)(_ => 1)(_ + _)
}

// Controllers

def getAverage(list:Iterable[Int]) = {
  list.sum / getCount(list)
}

def getMedian(list:Iterable[Int]) = {
  getMiddle(list.toList.sorted)
}
def getMode(list:Iterable[Int]) = {
 val frequencyMap = getFrequency(list.toList)
 frequencyMap.filter(item=>{
   item._2 == frequencyMap.valuesIterator.max
 })
}

val getMean = getAverage(_)

// View
def getStats(list:Iterable[Int]) = {
  Map(
	("mean",getMean(list)),
	("median",getMedian(list)),
	("mode",getMode(list))
  )
}

// Data
val data = List(100,2000,2,4151,1515,3,3)

// Rendering view
getStats(data)

Mi solución al reto:

// Utils
def getTotal(list:Iterable[Int]) = {
  list.reduce((item,next)=>item+next)
}
def getCount(list:Iterable[Int]) = {
  list.fold(0)((item,next)=>item+1)
}
def getMiddle(list:List[Int]) = {
  val middle = getCount(list).toFloat / 2
  if (middle.isValidInt) {
    (list(middle.toInt - 1),list(middle.toInt))
  }
  else {
    list(middle.floor.toInt)
  }
}
def getFrequency(list:List[Int]) = {
 list.toList.groupMapReduce(identity)(_ => 1)(_ + _)
}

// Controllers

def getAverage(list:Iterable[Int]) = {
  getTotal(list) / getCount(list)
}

def getMedian(list:Iterable[Int]) = {
  getMiddle(list.toList.sorted)
}
def getMode(list:Iterable[Int]) = {
 val frequencyMap = getFrequency(list.toList)
 frequencyMap.filter(item=>{
   item._2 == frequencyMap.valuesIterator.max
 })
}

val getMean = getAverage(_)

// View
def getStats(list:Iterable[Int]) = {
  Map(
	("mean",getMean(list)),
	("median",getMedian(list)),
	("mode",getMode(list))
  )
}

// Data
val data = List(100,2000,2,4151,1515,3,3)

// Rendering view
getStats(data)

Aqui va mi reto. Aún no me acostumbro a usar solo valores y no variables. jajajaja Esto de la inmutabilidad es dificil de adoptar jajajaj

import scala.collection.mutable
import scala.util.Random

object Measures extends App{

  val random = Random

  val input:Seq[Int]=for (i<- 1 to 13) yield random.nextInt(10)

  var lowest:mutable.PriorityQueue[Int]=mutable.PriorityQueue.empty[Int]
  var highest: mutable.PriorityQueue[Int]=mutable.PriorityQueue.empty[Int]

  var mediana:Double=0
  var moda:Seq[Int] = Seq.empty[Int]

  def media(x:Seq[Int]): Double = x.sum.toDouble/x.size

  def mediana(x:Int): Unit = {
    lowest.addOne(x)
    highest.addOne(-lowest.dequeue())

    if(highest.size>lowest.size){lowest.addOne(-highest.dequeue())}

    if(lowest.size>highest.size)mediana=lowest.head
    else mediana=(lowest.head-highest.head).toDouble/2
  }

  def calculateModa(): Seq[Int] = {

    val max:Int = input.groupBy(identity).maxBy(_._2.size)._2.size

    input.groupBy(identity).
      foreach { case (k, v) =>
        if (v.size == max) {
          moda=moda.appended(k)
        }
      }
  }

    println("Los datos ingresados son :")
    input.foreach(println(_))
    println( "La media de los datos ingresados es" + media(input))
    println("La mediana es :")
    input.foreach(mediana(_))
    println(mediana)
    if(calculateModa().isEmpty){println("No hay moda")}
    else{
      println("La moda es:")
      moda.foreach(println(_))
    }

}


La solución del reto la pueden encontrar aquí en mi GitHub: GitHub - @RianoJNicolas

scala> def promedio(lista:Seq[Int]):Unit ={
| val suma: Float= lista.sum.toFloat
| val tamanio= (lista.map(x=>1)).sum
| val promedio = suma/tamanio
| Map(“Media”-> promedio)
| println(promedio)
| }

scala> def mediana(lista:Seq[Int])={
| val tamanio= (lista.map(x=>1)).sum.toFloat
| val mitad = tamanio/2
| if (mitad%2==0){
| val mediana: Float = (lista(mitad.toInt-1)+lista(mitad.toInt))/2.toFloat
| Map(“Mediana”->mediana)}
| else Map(“Mediana”-> lista(mitad.toInt))
| }

scala> def moda(lista: Seq[Int])={
| lista.groupBy(x=>x).maxBy(x => x._2.size)
| }

Duda por que cuando haces le map a una lista por ejemplo
override def main(args: Array[String]): Unit = {
val numbers = List (1,2,3,4)
println(numbers)
val numbers2 = numbers.map(x => x+1)
println(numbers2)
}
}

en la salida me recorre el valor iniciando en 2, ósea si agrega el 5 en mi lista pero me quita el primer valor

List(1, 2, 3, 4)
List(2, 3, 4, 5)

scala> val mediana = (lista: List[Int]) => lista.sorted.lift(lista.size/2).get
mediana: List[Int] => Int = $$Lambda$1107/0x0000000801151040@9ab495b

scala> val moda = (lista: List[Int]) => lista.groupBy(identity).view.mapValues(_.size).maxBy(_._2)._1
moda: List[Int] => Int = $$Lambda$1108/0x0000000801151840@25bcbc72

scala> val media = (lista: List[Int]) => lista.sum / lista.size
media: List[Int] => Int = $$Lambda$1109/0x0000000801152840@1a1e5b4b

scala> val entrada = List(1, 5, 3, 7, 7, 8, 8, 9, 10, 1, 3, 5, 1, 1)
entrada: List[Int] = List(1, 5, 3, 7, 7, 8, 8, 9, 10, 1, 3, 5, 1, 1)

scala> Map("mediana" -> mediana(entrada), "moda" -> moda(entrada), "media" -> media(entrada))
res57: scala.collection.immutable.Map[String,Int] = Map(mediana -> 5, moda -> 1, media -> 4)```

Les comparto el código del ejercicio

object stats {
// Para la media o promedio
def media(l: Seq[Int]) : Double = l.sum.toDouble / l.size.toDouble
// Para la mediana
def mediana(l: Seq[Int]) : Double = {
if(l.size % 2 == 1) l(l.size/2) else (l(l.size / 2) + l((l.size / 2) - 1))/ 2
}
// Para la moda
def moda(l: Seq[Int]) : Double = l.groupBy(group => group).maxBy( num => num._2.size)._1
// Resultado
def resultado(l: Seq[Int]) : Map[String, Double] = {
Map((“Media”, media(l)),(“Medina”, mediana(l)),(“Moda”,moda(l)))
}
}
// Resultados
val lista = Seq(1, 6, 6, 5, 2, 3).sorted
stats.resultado(lista)

MEDIA

  1. Suma de los Elementos / Nº de Elementos

MEDIANA

  1. Orden de datos
  2. Verificar si el subset es par o impar
    2.1 Si es par, suma de la posicion de la mitad (entera) y la posicion anterior (-1) entre 2
    2.2 Si es impar, posicion de la mitad (entera)

MODA

  1. Agrupacion por numeros
  2. Conteo de cada numero
  3. Elegir el mayor de todos
// Code
scala> object reto {
     |   def media(lista: Seq[Int]): Double = {
     |           lista.sum.toDouble / lista.size.toDouble;
     |   }
     |   def mediana(lista: Seq[Int]): Double = {
     |           val ltOr = lista.sorted;
     |           if(ltOr.size%2 == 1){
     |                   ltOr(ltOr.size/2);
     |           }
     |           else{
     |                   ( ltOr(ltOr.size/2) + ltOr(ltOr.size/2 - 1) )/2
     |           }
     |   }
     |   def moda(lista: Seq[Int]): Double = {
     |           lista.groupBy(
     |					group => group
     |			 ).maxBy(
     |					num => num._2.size
     |			 )._1
     |   }
     |   def resultadoMap(lista: Seq[Int]): Map[String,Double] = {
     |           Map(
     |                   "Media" -> media(lista)
     |                   ,"Mediana" -> mediana(lista)
     |                   ,"Moda" -> moda(lista)
     |           );
     |   }
     | }
defined object reto

scala> val lista = Seq(1,2,4,4)
lista: Seq[Int] = List(1, 2, 4, 4)

scala> reto.resultadoMap(lista)
res2: Map[String,Double] = Map(Media -> 2.75, Mediana -> 3.0, Moda -> 4.0)

scala> conj.incl(12) <console>:26: error: value incl is not a member of scala.collection.immutable.Set[Int] conj.incl(12)

para agregar valores solo se usa el operador/método +
el valor es agregado en cualquier orden

Espero lograr el reto!

// Data Test Case
val nums = List(1,2,3,4,3,3)

// Functions for Average, Median and Mode
def average(nums: List[Int]) = {
val sum = nums.reduce( (x,y) => x+y)
sum / nums.size
}

def median(nums: List[Int] ) = {
val sorted = nums.sorted
sorted({sorted.size / 2} - 1) // 0 index based
}
def mode(nums: List[Int]) = {
nums.maxBy( x => nums.count(_ == x))
}
// Result in Map Format
val myMap = Map( “Avergae” -> average(nums), “Median” -> median(nums), “Mode” -> mode(nums2))
//val myMap: scala.collection.immutable.Map[String,Int] = Map(Avergae -> 2, Median -> 3, Mode -> 3)