{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "![](img/logocurso.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "nbpresent": {
     "id": "d9e822f9-0a52-43f2-90ef-e8fd6860aacc"
    }
   },
   "source": [
    "![](img/sesion2.png)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Diccionarios\n",
    "\n",
    "Los diccionarios son una generalización de listas o tuplas. En una lista utilizamos números (el número de orden) para designar cada valor."
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "lista=[\"Antonio\",   \"María\",   \"Andres\",  \"Fermina\",   \"Antonio\",   \"Catalina\"]\n",
    "        lista[0]     lista[1]   lista[2]    lista[3]     lista[4]     lista[5]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "En principio cada posición carece de un significado más allá del orden que ocupa cada valor de la lista. Pero pudiera ser que cada valor sí que tenga un significado particular y que deseemos designarlo teniendo esto en cuenta. Para ello podemos utilizar un diccionario."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "dicci={\"padre\":\"Antonio\",\"madre\":\"María\",\"abuelomat\":\"Andrés\",\"abuelamat\":\"Fermina\",\"abuelopat\":\"Antonio\",\"abuelapat\":\"Catalina\"}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "dicci[\"padre\"]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Un diccionario es, por tanto, un tipo de dato más flexible, de más alto nivel, que permite incorporar una clave identificativa para cada valor.\n",
    "* \"padre\", \"madre\", \"abuelomat\", \"abuelamat\",... son las **claves del diccionario**.\n",
    "* \"Antonio\", \"María\", \"Andrés\", \"Fermina\",... son los **valores del diccionario**.\n",
    "En una lista o tupla la clave identificativa es simplemente el orden que ocupa cada valor mientras que en un diccionario podemos escoger como clave cualquier tipo de dato **inmutable** que permita identificar de forma más intuitiva su correspondiente valor. Como vemos, para definir un diccionario se utiliza la sintaxis\n",
    "<div align=\"center\">{clave1:valor1,clave2:valor2,...}</div>\n",
    "o también\n",
    "<div align=\"center\">dict([(clave1,valor1),(clave2,valor2),...]).</div>\n",
    "\n",
    "Veamos diversos ejemplos que ilustran diferentes técnicas que podemos emplear con diccionarios:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Es posible asimismo utilizar notación comprensiba similar a la de las listas:\n",
    "diccicuadrados={x:x**2 for x in range(10)}\n",
    "print(diccicuadrados)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Es un diccionario simple con dos claves (1 y 3) y dos valores (3 y 4).\n",
    "diciosimple={1:2,3:4}\n",
    "diciosimple[1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Cuidado, 2 no es una clave, es un valor\n",
    "diciosimple[2]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Alternativamente, podriamos haver definido diciosimple mediante:\n",
    "diciosimple=dict([(1,3),(3,4)])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Es posible añadir más información a un diccionario:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "dicci[\"bisabuelapat\"]=\"Olegaria\"\n",
    "dicci[\"bisabuelopat\"]=\"Sisebuto\"\n",
    "print(dicci)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Asimismo podemos eliminar datos del diccionario:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "del(dicci[\"bisabuelopat\"])\n",
    "print(dicci)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Tambien se puede recorrer el diccionario con un bucle:\n",
    "for fami in dicci:\n",
    "    print(\"mi\",fami,\"es\",dicci[fami])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# O comprobar si una clave está o no en el diccionario\n",
    "print(\"padre\" in dicci)\n",
    "print(\"tio\" in dicci)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Algunas instrucciones útiles para manejar diccionarios son:\n",
    "* **nombrediccionario.items()**: proporciona los pares (clave, valor).\n",
    "* **nombrediccionario.values()**: proporciona los valores del diccionario.\n",
    "* **nombrediccionario.keys()**: proporciona las claves del diccionario\n",
    "\n",
    "Estas instrucciones siguen la notación de objetos que veremos más adelante y dan como resultado objetos iterables que pueden transformarse en listas aplicando la instruccion **list**.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(dicci.items())\n",
    "print(\"--------------------------\")\n",
    "print(\"- También en forma de lista\")\n",
    "print(list(dicci.items()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(list(dicci.values()))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(list(dicci.keys()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Ejercicios sobre diccionarios\n",
    "\n",
    "### Ejercicio 1\n",
    "Diseñar un diccionario que permita traducir las siguientes frases del español al inglés:\n",
    "* Yo soy muy inteligenge/simpático/guapo/generoso.\n",
    "* Mi padre es muy inteligenge/simpatico/guapo/generoso.\n",
    "Aplicarlo para traducir \"Mi padre es muy simpático\" y otras frases similares.\n",
    "<div class=\"alert alert-info\">\n",
    "Algunas instrucciones útiles:\n",
    "<ul>\n",
    "    <li>el método <b>cadena.split()</b> que produce una lista con las palabras que forman parte de <b>cadena</b>.</li>\n",
    "<li>el método <b>cadena.replace(viejo,nuevo)</b> que busca en <b>cadena</b> la subcadena <b>viejo</b> y la reemplaza por <b>nuevo</b>.</li>\n",
    "<li>el método <b>sep.join([cadena1,cadena2,...])</b> que une todas las cadenas <b>cadena1</b>, <b>cadena2</b>,... utilizando <b>sep</b> como separador en la unión.</li>\n",
    "</ul>\n",
    "</div>\n",
    "<b>Nota</b>: No es necesario utilizar todas estas instrucciones."
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "frase=\"hola como estás\"\n",
    "frase.split()\n",
    "\n",
    "Out[]:\n",
    "['hola', 'como', 'estás']\n",
    "\n",
    "\n",
    "frase.replace(\"hola\",\"adiós\")\n",
    "\n",
    "Out[]:\n",
    "'adiós como estás'\n",
    "\n",
    "\n",
    "\"-\".join(['hola', 'como', 'estás'])\n",
    "\n",
    "Out[]:\n",
    "'hola-como-estás'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 2\n",
    "Crear un diccionario que asigne a cada letra de una frase el número de ocurrencias de tal letra en la frase\n",
    "<div class=\"alert alert-info\">\n",
    "    Utilizar el método <b>secuencia.count(elemento)</b> para contar el número de veces que aparece elemento en secuencia</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(\"hola como estas amigooooo\".count(\"a\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "frase=\"En un país multicolor nació una abeja bajo el sol y fue famosa en el lugar por su alegría y su bondad\"\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "# Conjuntos\n",
    "\n",
    "Tanto en matemáticas como en Python, un conjunto es una colección de elementos que carece de orden. Un conjunto se caracteriza simplemente por aquellos elementos que está o no. Podemos definir un conjunto en Python utilizando la sintaxis\n",
    "<div align=\"center\">{elem1,elem2,elem3,...}</div>\n",
    "o también\n",
    "<div align=\"center\">set(lista/tupla)</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "lista=[1,2,2,2,5,4]\n",
    "conjunto1=set(lista)\n",
    "conjunto2={2,3,4,5,6,7}\n",
    "conjunto3={\"caniche\",\"podenco\",\"galgo\"}\n",
    "print(conjunto1,\"-\",conjunto2,\"-\",conjunto3)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Es posible definir conjuntos de forma comprensiba\n",
    "{abs(i) for i in range(-10,10)}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Podemos utilizar in/not in para comprobar si un elemento está o no en el conjunto\n",
    "2 in conjunto1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\"dalmata\" not in conjunto3"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Tenemos disponibles las operaciones habituales enter conjuntos\n",
    "print(conjunto1|conjunto2)    # unión\n",
    "print(conjunto1^conjunto2)    # intersección\n",
    "print(conjunto1-conjunto2)    # diferencia"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 3\n",
    "Dada una frase, calcular el número de consonantes diferentes que participan en ella."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Funciones\n",
    "\n",
    "En matemáticas una función es un método que produce un resultado en función de ciertos argumentos:\n",
    "<div align=\"center\">$f(x,y,z)=x^2+y^2+z^2$</div>\n",
    "Una vez definida la función podremos utilizarla indicando los valores concretos para los argumentos\n",
    "<div align=\"center\">$f(1,1,1)\\rightarrow 3$</div>\n",
    "En la mayoría de lenguajes informáticos es posible utilizar funciones de forma muy similar. Las funciones retornarán un resultado a partir de una lista de argumentos. La sintaxis básica para una función en Python es"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "def nombrefuncion(arg1,arg2,arg3,...):\n",
    "    instruccion1\n",
    "    instruccion2\n",
    "    ...\n",
    "    return valor"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Definimos la función de antes en Python\n",
    "def f(x,y,z):\n",
    "    return x**2+y**2+z**2\n",
    "f(1,1,1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "A partir del momento de la definición Python recordará la función y podremos ejecutarla sin más que indicar su nombre y argumentos."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Una función en varias variables como\n",
    "<div align=\"center\">$\\begin{array}{c}g:\\mathbb{R}^3\\rightarrow \\mathbb{R}^2\\\\g(x,y,z)=(x-y^2+z^3,2^{x+y-z})\\end{array}$</div>\n",
    "afrece como resultado un vector o lista. Podemos programarla en Python como:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def g(x,y,z):\n",
    "    return [x-y**2+z**3,2**(x+y-z)]\n",
    "g(1,1,2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Podemos definir también funciones sin argumentos que simplemente realizan una acción.\n",
    "def ponhola():\n",
    "    print(\"hola\")\n",
    "    return\n",
    "ponhola()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 4\n",
    "Transforma en funciones las instrucciones de los tres primeros ejercicios."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 5\n",
    "* Define la función fibonaccilista(n) que proporciona una lista con los n primeros términos de la sucesión de Fibonnaci.\n",
    "* Define la función fibonacci(n) que proporciona el n-ésimo términos de la sucesión de Fibonnaci."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Argumentos de una función\n",
    "\n",
    "Python permite manejar los argumentos de una función de forma muy versátil en varias modalidades:\n",
    "<div class=\"alert alert-info\"><b>Argumentos con palabra clave y valor por defecto</b>: En la definición es posible especificar valores por defecto para algunas de las variables (han de ir al final). Luego, al utilizar la función si no indicamos el valor de esas variables, se tomará su valor por defecto</div>"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "def ejem1(       x,   y,             z=1,   w=\"hola\"        ):\n",
    "        sin valor por defecto     con valor por defecto\n",
    "       argumentos posicionales   argumentos con palabra clave"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def ejem1(x,y,z=1,w=\"hola\"):\n",
    "    return [x,y,z,w]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Si no indicamos alguna de las variables que tiene valor por defecto, se tomará para ella el valor que se especificón en la\n",
    "# definición. En principio el orden de las variables es el mismo que en la definición tomándese de izquierda a derecha.\n",
    "print(ejem1(1,2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(ejem1(1,2,3))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Las variables que tienen valor por defecto pueden utilizarse como una clave que puede utilizarse para asignar su valor\n",
    "# sin necesidad de respetar el orden normal con que se definió la función.\n",
    "print(ejem1(1,2,w=3,z=4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "print(ejem1(1,2,w='adios'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Las argumentos con palabra clave pueden indicarse en cualquier orden pero siempre al final tras \n",
    "# los argumentos posicionales.\n",
    "ejem1(z=1,2,1)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-info\"><b>Número variable de argumentos/argumentos con valor por defecto</b>:\n",
    "<ul>\n",
    "    <li><b>&#42;l:</b> Indica un número variable de argumentos que se almacenarán en <b>l</b> en forma de tupla.</li>\n",
    "    <li><b>&#42;&#42;d:</b> Indica un número variable de argumentos con valor por defecto que se almacenarán en <b>d</b> como un diccionario. Este tipo de argumento variable para variables con palabra clave y valor por defecto debe situarse siempre en la posición final.</li>\n",
    "</ul></div>"
   ]
  },
  {
   "cell_type": "raw",
   "metadata": {},
   "source": [
    "def ejem2(    x,  y,                   *l,                          **d):\n",
    "            variables normales       número variable de          número variable de\n",
    "            sin valor por defecto    variables posicionales      variables clave con valor por defecto\n",
    "            variables posicionales   se almacenan en la tupla l  se almacenan en el diccionario d\n",
    "Por ejemplo\n",
    "            ejemp2( 3, 2,    6,4,9,                    w=4,r=5,t=\"hola\",s=\"adios\")\n",
    "                    x  y     estos tres argumentos     estas cuatro variables con clave y valor por defecto\n",
    "                             se asignarían a l         se asignarían a d\n",
    "                             formando la tupla         formando el diccionario\n",
    "                             l=[6,4,9]                 d={'w':4,'r':5,'t':'hola','s':'adios'}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def ejem2(x,y,*l,**d):\n",
    "    return (x,y,l,d)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Los dos primeros argumentos serán x e y, luego podemos incluir: \n",
    "#                                             * todos los argumentos posicionales que deseemos que se incluirán en l\n",
    "#                                             * todos los argumentos con variable clave y valor inicial que queramos que\n",
    "#                                               pasarán a formar d\n",
    "print(ejem2(3,2,6,4,9,w=4,r=5,t=\"hola\",s=\"adios\"))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Aquí, tras indicar x e y no se incluye ningún argumento posicional así que l estará vacío.\n",
    "print(ejem2(1,2,altu=4))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Si solo indicamos x e y, tanto l como d serán vacíos\n",
    "print(ejem2(1,2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 6\n",
    "Definir una función en la que indicando p y un vector de cualquier dimensión, $v=(v_1,v_2,\\ldots,v_n)$, proporciona la norma $\\|v\\|_p=(v_1^p+v_2^p+\\cdots+v_n^p)^{\\frac{1}{p}}$. Resolver de dos maneras: 1) indicando p como argumento posicional inicial y 2) indicando p como variable con valor por defecto p=2 (norma cuadrática)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 7\n",
    "Diseñar la función **mifamilia** que reciba la siguiente información para una familia:\n",
    "* nombre del padre,\n",
    "* nombre de la madre,\n",
    "* edad de cada uno de los hijos,\n",
    "* parientes adicionales cada uno con su grado de parentesco y nombre,\n",
    "en la forma\n",
    "<div align=\"center\">mifamilia(\"Antonio\",\"Daniela\",3,5,11,4,Abuela='Maricarmen',Tia='Lola')</div>\n",
    "y que produzca como resultado un texto descriptivo de la familia del tipo:\n",
    "<div align=\"center\">Mi familia se compone de mi, Antonio, mi conyuge, Daniela, 4 hijos con edades, 3, 5, 11, 4, junto con Abuela Maricarmen, Tia Lola</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Programación funcional\n",
    "En Python es posible pasar una función como parámetro de otra función. Ello permite definir funciones que utilizan otras funciones para crear estructuras más complejas."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def f(x):\n",
    "    return x**2\n",
    "def g(x):\n",
    "    return x**3\n",
    "\n",
    "def sumaleuno(fun,x):\n",
    "    return fun(x)+1\n",
    "\n",
    "print(sumaleuno(f,2))\n",
    "print(sumaleuno(g,2))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 8\n",
    "Definir una función **lamasgrande** que para cualquier otra función (al estilo de f(x) o g(x) utilizadas antes) y cualquier valor x, indique el nombre de la función que ofrece el mayor valor para x.\n",
    "\n",
    "Indicación: Podemos utilizar la propiedad de los objeto función __name__ que permite obtener el nombre de la función de modo que\n",
    "<div align=\"center\">f.__name__ = nombre de la función f</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "        "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 9\n",
    "Define una función que para cualquier otra proporcione una nueva función que ofrezca como resultado una lista en la que aparece el nombre de la función inicial y el resultado que ella ofrece"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Las funciones como la que obtenemos en el último ejercicio que a partir de una función generan otra que añade información o funcionalidades adicionales a la función inicial son lo que se denominan **decoradores**."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Disponemos de diversas instrucciones para aplicar funciones de forma repetida o reiterada sobre listas de elementos:\n",
    "<div class=\"alert alert-info\"><b>filter(func,secuencia)</b>: Elimina los elementos de secuencia para los cuales la función <b>func</b> da valor false</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def mult7(x):\n",
    "    return x%7==0\n",
    "list(filter(mult7,[1,2,3,7,14,15,21,28,30]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-info\"><b>map(func,secuencia)</b>: Aplica la función <b>func</b> a todos los elementos de la secuencia.</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def doble(x):\n",
    "    return 2*x\n",
    "\n",
    "list(map(doble,[1,2,3,4,5,6]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<div class=\"alert alert-info\"><b>reduce(func,secuencia)</b>: Aplica reiteradamente la función <b>func</b> a los dos primeros números de la secuencia y reutiliza el resultado para ir aplicando lo sucesivamente a los siguientes elementos. Para utilizar esta instrucción es preciso importarla del paquete functools</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from functools import reduce\n",
    "\n",
    "def producto(x,y):\n",
    "    return x*y\n",
    "\n",
    "reduce(producto,[1,4,5,7])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Funciones Lambda (funciones puras)\n",
    "\n",
    "Las funciones lambda son funciones que se utilizan en el momento y no requieren definición inicial. La sintaxis es\n",
    "<div align=\"center\">lambda variable: formula</div>"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "(lambda x:x**2)(2)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Utilizándolas es posible evitar definir funciones que luego solamente hemos de utilizar en un punto concreto."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "reduce(lambda x,y:x*y,[1,4,5,7])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "En python podemos utilizar una versión del condicional if-else en linea con la sintaxis:\n",
    "<div align=\"center\">valorverdadero <b>if</b> condicion <b>else</b> valorfalso</div>\n",
    "Esta versión en línea del condicional puede utilizarse en combinación con las funciones lambda."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "x,y=1,3\n",
    "\n",
    "\"Con estos valores tenemos que x \"+(\"es mayor\" if x>y else \"es menor\")+\" que y\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  Ejercicios de funciones\n",
    "\n",
    "\n",
    "### Ejercicio 10\n",
    "Implementa una función que seleccione la palabra de longitud más larga de entre una lista dada de palabras."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 11\n",
    "* Implementa una función que reciba una lista de enteros y calcule su media aritmetica.\n",
    "* Implementa una función que calcule el factorial de un número."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 12\n",
    "Implementa una función que, dado un carácter a elegir, elimine de un texto todas aquellas palabras que no contenga dicho carácter."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Ejercicio 13\n",
    "\n",
    "Escribir una función que reciba un texto y para cada caracter presente en el texto devuelva la cadena más larga en la que se encuentra ese caracter. Utiliza de apoyo un diccionario de { letra : palabra }, para cada letra de la cadena, lleva asociada la cadena más larga que la contiene:\n",
    "\n",
    "    \"En un lugar de la mancha\"\n",
    "\n",
    "    {'a': 'mancha', 'c': 'mancha', 'e': 'en', 'g': 'lugar', 'h': 'mancha', 'm': 'mancha', 'l': 'lugar', \n",
    "     'n': 'mancha', 'r': 'lugar', 'u': 'lugar'}"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
