Colecciones de datos y algoritmos en Python: de cero al infinito - Silvia Guardati Buemo - E-Book

Colecciones de datos y algoritmos en Python: de cero al infinito E-Book

Silvia Guardati Buemo

0,0

Beschreibung

Solucionar uno mismo los problemas derivados del análisis de las colecciones de datos por medio del diseño de algoritmos es esencial para evolucionar como programador, así como saber implementar dichas soluciones utilizando el lenguaje de programación Python. Si quiere aprender nuevas formas de representar datos, su manejo y su uso en la solución de problemas, este libro le proporcionará todo lo que necesita. En él se mantiene la premisa de que enseñar a programar debe ir más allá de explicar un lenguaje de programación, debe desarrollar la capacidad de análisis, despertar el interés por diseñar soluciones eficaces y eficientes, promover la escritura de código agradable de leer y, por lo tanto, fácil de mantener y evolucionar, y debe convencer acerca de la importancia de probar todos los algoritmos, para asegurarse de que funcionan correctamente. Este manual se organiza en cuatro capítulos: el primero está dedicado a las listas; el segundo, a los conjuntos; el tercero, a los diccionarios, y el cuarto, a los arreglos. Cada tema se desarrolla poniendo especial énfasis en el concepto, dado que lo importante es entender la teoría para luego poder llevarla a la práctica y usarla en el diseño de algoritmos con éxito. Además, todos los programas escritos en Python, presentados como ejemplos o como solución a los problemas, pueden consultarse en un repositorio de GitHub. Sin duda, este es un libro imprescindible para todos aquellos que tengan conocimientos básicos de algorítmica y quieran profundizar en esta área. También se ajusta muy bien a materias de ciencias de la computación dedicadas a la enseñanza del desarrollo de algoritmos y su implementación usando lenguajes de programación, por lo que es el manual ideal para las primeras materias de cualquier plan de estudios que incluya este campo del saber. Si antes de profundizar en este libro quiere asentar las bases del pensamiento algorítmico e introducirse en algunos de los elementos básicos del lenguaje, le recomendamos el libro Aprende a programar en Python: de cero al infinito.

Sie lesen das E-Book in den Legimi-Apps auf:

Android
iOS
von Legimi
zertifizierten E-Readern

Seitenzahl: 195

Das E-Book (TTS) können Sie hören im Abo „Legimi Premium” in Legimi-Apps auf:

Android
iOS
Bewertungen
0,0
0
0
0
0
0
Mehr Informationen
Mehr Informationen
Legimi prüft nicht, ob Rezensionen von Nutzern stammen, die den betreffenden Titel tatsächlich gekauft oder gelesen/gehört haben. Wir entfernen aber gefälschte Rezensionen.



 

 

Colecciones de datos y algoritmos en Python: de cero al infinito

Silvia Guardati Buemo

Derechos reservados © Alfaomega Grupo Editor, S.A. de C.V., México

Primera edición: 2022

ISBN: 978-842-673-556-0

Primera edición: MARCOMBO, S.L. 2023

© 2023 MARCOMBO, S.L.

www.marcombo.com

Cualquier forma de reproducción, distribución, comunicación pública o transformación de esta obra sólo puede ser realizada con la autorización de sus titulares, salvo excepción prevista por la ley. Diríjase a CEDRO (Centro Español de Derechos Reprográficos, www.cedro.org) si necesita fotocopiar o escanear algún fragmento de esta obra

ISBN: 978-84-267-3556-0

Producción del ePub: booqlab

Acerca de la autora

MC. Silvia Guardati Buemo es profesora del Departamento Académico de Computación, del Instituto Tecnológico Autónomo de México (ITAM), desde 1988. Sus principales áreas de enseñanza son: algoritmos, estructuras de datos e ingeniería de software. También ha participado en proyectos de diseño de procesos y control de calidad relacionados con la industria del software.

Es autora de varios libros de texto, entre los que destacan “Estructuras de Datos” (ed. McGraw Hill), “Estructuras de Datos: Algoritmos en C++” (ed. Pearson), “Estructuras de Datos Básicas. Programación Orientada a Objetos con Java” (ed. Alfaomega), “From Zero to Infinity. Learn to Program in Java” (Amazon) y “Aprende a programar en Python: de cero al infinito” (Marcombo).

Agradecimientos*

Agradezco el apoyo recibido para la realización de este libro al Dr. Alejandro Hernández, vicerrector del ITAM, al Dr. Ante Salcedo, director de la División Académica de Ingeniería del ITAM, y al Dr. Fernando Esponda, jefe del Departamento Académico de Computación del ITAM.

Agradezco, además, a mis alumnos. Son ellos los que mantienen viva la pasión por la enseñanza, los que me permiten experimentar, una y otra vez, el placer de entrar al salón de clases para contribuir en el descubrimiento de sus habilidades y su desarrollo como individuos y, con un poco de suerte, en la construcción de un mundo mejor.

También agradezco al DG Lisandro Lazzaroni por el diseño de la portada de este libro; por darle una pincelada de naturaleza al mundo de los algoritmos.

 

 

 

 

* Apoyo financiero otorgado por parte de la Asociación Mexicana de Cultura, A.C.

Contenido

Acerca de la autora

Agradecimientos

Prefacio

Capítulo 1

Listas

1.1 Introducción

1.2 Operaciones

1.3. Listas anidadas

1.4 Listas por comprensión

1.5 Otras funciones incorporadas: filter, map y zip

1.6 Problemas de práctica

Capítulo 2

Conjuntos

2.1 Introducción

2.2 Operaciones de inserción y eliminación

2.3 Operaciones entre conjuntos

2.4 El tipo de dato frozenset

Capítulo 3

Diccionarios

3.1 Introducción

3.2 Operaciones

3.3 Diccionarios y algo más

3.4 Diccionarios por comprensión

3.5 Paso de parámetros y diccionarios

3.6 Diccionarios y conjuntos

3.7 Diccionarios y la función enumerate

3.8 Diccionarios en la solución de problemas

Capítulo 4

Arreglos

4.1 Introducción

4.2 Construcción de arreglos

4.3 Operaciones en arreglos

4.4 Más operaciones con arreglos

4.5 Arreglos y archivos

4.6 Implementación de operaciones con arreglos

4.6.1 Búsqueda

4.6.2 Inserción

4.6.3 Eliminación

4.6.4 Ordenación

4.7 Solución de problemas usando arreglos

4.8 Arreglos de 2 dimensiones

4.8.1 Creación de arreglos bidimensionales y asignación de valores

4.8.2 Acceso a los elementos de los arreglos bidimensionales

4.9 Solución de problemas usando arreglos bidimensionales

4.10 Arreglos de n dimensiones

 

Índice temático

Prefacio

Este libro es el resultado de muchos años de enseñanza de materias en las cuales el objetivo principal es despertar en los alumnos el gusto por resolver problemas usando algoritmos. La idea de enseñar a programar debe ir más allá de enseñar un lenguaje de programación, debe desarrollar la capacidad de análisis, despertar el interés por diseñar soluciones eficaces y eficientes, promover la escritura de código agradable de leer y, por lo tanto, fácil de mantener y evolucionar. Además, debe demostrar y convencer acerca de la fundamental importancia de probar todos los algoritmos, asegurándose que funcionan correctamente.

Este libro es la continuación natural del libro: “Aprende a programar en Python: de cero al infinito”, de la misma autora. En el primer libro se asentaron las bases del pensamiento algorítmico y se introdujeron algunos de los elementos del lenguaje. En este libro se estudiarán nuevas formas de representar los datos, su manejo y su uso en la solución de problemas. Hay que tener en cuenta que, si se trabaja solo con uno o dos números, el conjunto de problemas que se puede resolver es muy limitado. Si, además de números, se cuenta con las cadenas de caracteres, los números complejos y las tuplas, entonces el conjunto de problemas se amplía. Por lo tanto, si ahora se agregan nuevos tipos y nuevas formas de almacenar datos en la memoria del ordenador, la variedad de problemas que se podrán abordar algorítmicamente se incrementa notoriamente.

El objetivo principal de este libro es enseñar tipos estructurados de datos, aplicados en la solución algorítmica de problemas. El material está organizado en cuatro capítulos, el primero dedicado a las listas, el segundo a los conjuntos, el tercero a los diccionarios y el cuarto a los arreglos. Cada tema se presenta poniendo especial énfasis en el concepto porque lo importante es entenderlo y poder, posteriormente, usarlo en el diseño de algoritmos. Para su implementación, se utiliza el lenguaje Python.

Como en el caso del libro anterior, se aplica un enfoque iterativo-incremental. Es decir, se dividió el estudio del contenido del libro en partes (iteraciones) y en cada iteración se presentan algunos conceptos (incrementos). Estos se aplican en la solución de problemas y se pasa a la siguiente iteración, en la cual se incorporan nuevos conceptos y, ahora, en la solución de problemas se emplean los conocimientos nuevos y los previos, y así se continúa hasta cubrir todos los temas del libro. Por la fuerte relación que existe con el material del primer libro, se puede afirmar que, con este libro, simplemente se sigue iterando e incrementando lo aprendido hasta el momento.

Considerando que la idea central es continuar desarrollando el pensamiento algorítmico, se enfatiza la importancia de la práctica para poder asimilar los conocimientos. A lo largo de todo el libro se recomienda fuertemente que, una vez estudiado y entendido el concepto, realice la mayor cantidad posible de problemas. En cada capítulo se incluyen varios problemas con sus soluciones. Como se supone que el lector ya cuenta con las bases del pensamiento algorítmico que le permite entender las soluciones, no se incluyeron diagramas de flujo. Sin embargo, los diagramas de flujo son fuertemente recomendados para todos aquellos que aún no han ganado seguridad en el diseño de algoritmos. En todos los problemas se sugiere que primero realice su propia solución y luego la compare o la revise con respecto a la proporcionada en el libro. Para algunos problemas también se desarrolló un vídeo, en el cual se muestra y explica la solución propuesta. En este caso, junto al problema aparece la letra V.

Asimismo, se sigue resaltando la importancia de las pruebas durante el proceso de desarrollo de todo producto de software. En algunos algoritmos se incluyen pruebas estáticas de caja blanca, los mapas de memoria, para comprobar el buen funcionamiento de estos. Además, para probar los programas escritos, se ejecutan pruebas dinámicas de caja negra. Estas se documentan en el libro por medio de algunos casos de prueba.

Recuerde que es de fundamental importancia que:

1. Lea y analice cuidadosamente el problema: identifique los datos y el resultado esperado.

2.Diseñe la solución: pasos u operaciones (algoritmo) requeridos para alcanzar el resultado. Al algoritmo lo puede representar por medio de un diagrama de flujo o escribir en seudocódigo.

3.Pruebe la solución diseñada por medio de un mapa de memoria o prueba de escritorio.

4. Si detecta errores, vuelva al paso 2 para corregir el algoritmo.

5.Implemente su solución: codifique su algoritmo usando el lenguaje Python.

6.Pruebe la solución codificada por medio de ejecuciones del programa con diferentes casos de pruebas. Intente con diversas entradas: los datos más frecuentes o esperados, los que representan valores extremos, aquellos que por su valor pueden ocasionar errores de ejecución, etc.

7. Si detecta errores, vuelva al paso 5. Puede suceder que el error tenga origen en el diseño, no en la implementación. Si así fuera, entonces vuelva al paso 2.

8. ¿Llegó a este paso? ¡Felicidades!..., pero no se relaje. Revise su solución con las siguientes cuestiones en mente: ¿se puede hacer más eficiente?, ¿más legible?, ¿más simple?, ¿desarrolló un código que podría reusarse? Conviértase en su propio “abogado del diablo”.

Material de apoyo web

Todos los programas presentados como ejemplos o como solución a los problemas pueden consultarse online. Entre en www.marcombo.info con el código PYTHON10 para acceder a ellos.

En todos los programas se han incluido comentarios describiendo el problema que resuelve. Sin embargo, en el libro, y por razones de espacio, se han suprimido muchos de ellos. Es importante destacar que, en el libro, la falta de comentarios no afecta porque el programa aparece junto al enunciado del problema.

CAPÍTULO 1

LISTAS

1.1 INTRODUCCIÓN

Las listas son datos estructurados; es decir, son datos formados por más de un elemento o componente. Las listas están presentes en muchas y muy variadas situaciones; por ejemplo, la lista de alumnos inscritos a cierto curso, la lista de productos a comprar en el supermercado, la lista de clientes de un banco, solo por citar algunas.

Una lista hace referencia a una colección de datos que pueden ser números, cadenas o de algún otro tipo. Una característica importante de las listas es que son colecciones ordenadas de datos, lo que implica que importa el orden en el cual se encuentran sus elementos. Así, el primer dato ocupa la posición 0, el segundo la 1 y así sucesivamente. Otra característica igualmente importante de las listas es que son mutables. En Python los datos pueden ser mutables o inmutables, indicando con esto si pueden o no cambiar su valor una vez definidos. Ejemplos de inmutables son los números y las cadenas, mientras que las listas son un buen ejemplo de datos mutables. Por lo tanto, una vez creada una lista, esta puede modificarse: se le pueden agregar o quitar elementos.

Las listas, en Python, están representadas por el tipo list y, para definirlas, se utiliza la siguiente sintaxis:

Se escribe el nombre de la variable tipo lista seguido del signo de asignación y, a continuación, se listan todos los valores que forman la lista, separados por coma y entre []. Los elementos de una lista pueden ser de cualquier tipo, incluso puede haber de tipos diferentes en una misma lista. En este caso, habría que cuestionarse la utilidad o no de tener una lista así, pero el lenguaje lo permite. También es posible definir una lista usando el constructor list(). Este concepto no es tema de estudio en este libro. Sin embargo, se puede explicar de manera muy simple diciendo que es un método que permite construir e inicializar objetos de cierto tipo, en este caso tipo lista. Si se quiere darle valores iniciales, el parámetro debe ser una secuencia: rango, cadena, tupla o lista. Es decir, alguna secuencia iterable. En el ejemplo 1_1 se presentan algunas listas creadas de las dos formas descritas.

Ejemplo 1_1.py

Para generar la lista palabras se utiliza una función de las cadenas de caracteres, split(), la cual parte la cadena de acuerdo con el carácter dado como parámetro y devuelve una lista formada con las subcadenas que se encuentran entre dicho carácter. Por omisión, el valor del parámetro es un espacio en blanco (' '). En el ejemplo también se crean dos listas vacías; en la primera no se incluyen elementos entre los [] y, en la segunda, el constructor list no recibe un parámetro. La ejecución de estas líneas de código genera la siguiente salida en la terminal:

Observe que el contenido de la lista se despliega entre []. En los resultados obtenidos, también aparece el tipo de la variable precios, que es el tipo list en Python.

1.2 OPERACIONES

Las listas son datos estructurados con los cuales se pueden hacer una gran variedad de operaciones. Además, hay varias funciones predefinidas en el lenguaje que son aplicables a estas. A continuación, se irán explicando las más usadas y se complementará con ejemplos.

En los ejemplos se incluyen algunas instrucciones que producen errores. Estas están comentadas por lo que, para probar el código, deberá quitarle el comentario. Tenga en cuenta que, para probar las demás instrucciones, deberá comentar nuevamente las líneas conflictivas.

Acceso a los elementos:

A los elementos se puede acceder por medio de un índice, valor entero escrito entre []. Como ya se mencionó, las listas son una colección ordenada; por lo tanto, se puede hacer referencia a cada uno de los miembros por medio de la posición que ocupa en la lista. Los índices positivos son para ubicar a los elementos de izquierda a derecha, siendo 0 la posición del primero. Por su parte, los índices negativos son para ubicar a los elementos de derecha a izquierda, siendo -1 la posición del último. Si el índice tiene un valor fuera del tamaño de la lista, entonces se lanza la excepción: IndexError: list index out of range. Es importante mencionar que en muchos lenguajes de programación no se pueden usar índices negativos.

En la figura 1.1 se presenta gráficamente la lista colores_primarios, que tiene 3 elementos de tipo cadena de caracteres.

Figura 1.1. Acceso a los elementos de una lista

• Con colores_primarios se hace referencia a toda la lista.

• Con colores_primarios[0] se hace referencia al dato ubicado en la posición identificada con 0. En este caso, la palabra rojo.

• Con colores_primarios[-1] se hace referencia al dato ubicado en la última posición o en la primera si se considera de derecha a izquierda. En este caso, la palabra azul.

Operadores + y * con listas:

Los operadores + y * son operadores sobrecargados, como ya se señaló en el libro anterior al aplicarlos con números y cadenas de caracteres, que pueden operar con listas. El efecto del primero es concatenar o pegar los elementos de una lista al final de otra, mientras que el * se utiliza para repetir la secuencia de elementos de la lista tantas veces como lo indique el valor que acompaña al operador.

En el ejemplo 1_2 se muestran algunas líneas de código con el uso de índices para acceder a los elementos de una lista, así como de los operadores + y *.

Ejemplo 1_2.py

Una vez ejecutado el código del ejemplo anterior se tiene la siguiente salida en la terminal:

Funcionesasociadas a las listas:

Existen varias funciones predefinidas en Python dedicadas a operar con las listas. En la tabla 1.1 se presentan algunas de ellas con una explicación y, en el ejemplo 1_3, se muestra el uso de estas.

Tabla 1.1. Algunas funciones para el manejo de listas

A continuación se presenta el ejemplo 1_3, en el cual se utilizan todas las operaciones explicadas hasta aquí.

Ejemplo 1_3.py

Partición o división de listas (slicing):

Se pueden generar sublistas a partir de una lista por medio de la partición (división) o slicing. El concepto es el mismo que se estudió y aplicó en las cadenas de caracteres, capítulo 2 del libro 1. Para obtener una sublista se usa la sintaxis:

El resultado es una lista formada por los elementos de la lista ubicados desde la posición inicio hasta la (fin – 1) inclusive, tomados de n en n. Si el valor de fin es mayor que la longitud de la lista, copia hasta el último sin provocar error. Recuerde que el valor por omisión para inicio es 0, para fin es la longitud de la lista y para n es 1. Además, cualquiera de los tres parámetros puede ser un valor negativo. La lista original no se modifica. En el ejemplo 1_4 se presentan varios casos de generación de sublistas y la aplicación de esta operación combinada con otras.

Ejemplo 1_4.py

Al ejecutar el ejemplo anterior se obtiene la siguiente salida en la terminal:

Copiado de listas:

El copiado de listas es también una operación muy útil cuando se requiere manejar distintas versiones de estas. En Python se cuenta con dos tipos de copias:

• Copia superficial: se crea la nueva lista y luego se copian en ella las referencias (las direcciones) a los elementos de la lista original.

• Copia profunda: se crea la nueva lista y luego se insertan en ella copias de los elementos de la lista original.

El efecto de usar la copia superficial o profunda no se nota cuando se trabaja con datos inmutables porque, como ya se mencionó, estos no pueden modificarse una vez definidos. La diferencia se manifiesta cuando se tienen datos mutables, ya que con la superficial es el mismo dato (objeto), al cual se accede a través de dos variables distintas, y, por lo tanto, cualquier cambio realizado en la original o en la copia repercute en la otra. En el caso de la copia profunda, se crean copias de los elementos (objetos) y, por lo tanto, los cambios aplicados a la lista original no repercuten en la copia y viceversa. Cada una de estas formas de copiado tiene una función asociada, que son las funciones copy() y deepcopy(), respectivamente. Ambas se encuentran en el módulo de Python llamado copy.

La operación de partir o dividir una lista (slicing) también permite copiar una lista. En este caso también es un copiado superficial y habrá que tenerlo en cuenta cuando se trabaja con listas de datos mutables. En el ejemplo 1_5 se presentan algunas líneas de código para copiar listas, algunas con datos mutables y otras con datos inmutables para ayudar a entender estos conceptos. Observe que se debe importar el módulo copy.

Ejemplo 1_5.py

A continuación, se muestra el resultado obtenido al ejecutar las líneas precedentes.

En la siguiente sección del ejemplo, se presentan algunos casos de copiado de listas que almacenan datos mutables.

Ejemplo 1_5.py (cont.)

En las listas de listas se usaron dos índices para hacer referencia a los elementos de las listas internas. Por su importancia, sobre este tema se volverá en la sección 1.3. A continuación, se presentan los resultados de la ejecución del código anterior.

Por último, en el ejemplo se incluyeron algunos casos de copiado de listas utilizando la partición o slicing.

Ejemplo 1_5.py (cont.)

La ejecución de las líneas precedentes genera la siguiente salida en la terminal.

Comparación de listas:

Las listas pueden compararse entre sí usando los operadores relacionales: ==, !=, >, <, >= y <=. Otros operadores válidos con listas son los operadores de identidad y de pertenencia.

Cuando se aplica un operador relacional a dos listas, los elementos de estas se comparan, internamente, hasta poder determinar si cumplen o no la relación que se está evaluando. Por ejemplo, si se quiere comprobar que una lista es igual que otra, se compara elemento por elemento de ambas listas hasta que se terminan de recorrer las dos, en dicho caso son iguales; o bien, hasta que se llega a un par de elementos distintos o una lista termina y la otra no y, en cualquiera de estos casos, se concluye que las listas no son iguales. En el ejemplo que se muestra más abajo, se puede observar que si se compara si una lista es igual que otra y estas tienen distintos tipos de elementos, la respuesta es False pero no marca error. En cambio, si se trata de determinar si una lista es menor o mayor que otra se debe cumplir la condición de que las listas almacenen datos del mismo tipo. De lo contrario, se provoca un error de tipo TypeError.

En el ejemplo 1_6 se presentan algunos casos de uso de estos operadores para ayudar a una mejor comprensión de los mismos.

Ejemplo 1_6.py

Al ejecutar el código del ejemplo anterior se obtiene la siguiente salida en la terminal.

A continuación, se plantean algunos problemas en los que deberá aplicar los conceptos estudiados hasta aquí. Recuerde los pasos planteados en el prefacio: analice, diseñe, implemente y pruebe. En todos los problemas se propone una solución. Se sugiere que la revise una vez haya desarrollado su propia solución. En caso contrario, es más difícil pensar de manera independiente. Todos los programas se encuentran en el repositorio mencionado en el prefacio.

Problema 1.1

Escriba una función que reciba una lista y que devuelva como resultado una tupla almacenando el primer y el último elemento de la lista. En caso de que la lista no tenga dos o más elementos, debe lanzar una excepción.

Este es un problema cuya solución es muy simple, algorítmicamente hablando. Pero exige haber entendido qué son las listas y cómo se manejan sus elementos. A continuación, se señalan los principales pasos del algoritmo en seudocódigo.

1. Validar si el parámetro recibido es un dato.

2. Validar si la lista tiene, al menos, dos elementos.

3. Formar una tupla con el primero y el último.

4. Devolver el resultado.

5. En caso de error en los puntos 1 o 2, lanzar una excepción.

Programa 1_1.py

A continuación, se presentan los resultados obtenidos al probar la solución. Observe que los casos de prueba (CP) 3 y 4 cubren posibles errores: en el 3 se da una lista que no tiene, por lo menos, 2 elementos para poder obtener el primero y el último. Y en el 4, a la variable se le asigna el valor None y, por lo tanto, no se tiene una lista.

Problema 1.2