cace0353
19/04/14, 17:33:40
Desde el primer dia que me metí con Tasker para probar "cosas", leí en los tutoriales que Tasker no trabajaba con matrices de datos sino que empleaba "falsas matrices". Esto me dejó un poco descolocado...
Luego, con el desarrollo de un par de Proyectos que incluian y manejaban bases de datos, he visto que, una vez le has cogido el tranquillo y has leido Proyectos tan elaborados y complejos como, por ejemplo, el de mlsir (Whatsapp sin manos), realmente SI que podemos llamarlas matrices. Construidas de otro modo, de acuerdo, pero matrices al fin y al cabo.
De todas formas me viene a la cabeza un chiste del recordado Eugenio que decia, después del Ya sabeis aquel..:
Se encuentran dos amigos y uno le dice al otro:
¿Como lo haces para conservarte tan joven?
Pues no discutiendo con nadie!
Por eso no será...
Bueno, pues no será por eso...
Así que, si quereis, podeis llamarlas Matrices, Arrays o Arreglos (así no, por favor!)
Por mi parte, como estoy acostumbrado a llamarlas Matrices, voy a usar este nombre a lo largo de este trabajo. Además tiene otra acepción en el diccionario: "Entidad generadora de otras" que se ajusta exactamente a lo que son como vereis más adelante.
OBJETIVO DEL TRABAJO
El objetivo fijado es allanar la comprensión de conceptos básicos sobre las variables (para los que empiezan o no se atreven con ellas) y facilitar estructuras simples de creación, manipulación y procesamiento de matrices de datos con ejemplos ilustrativos. El disponer de un almacén de datos es esencial para muchos de los programas que se nos ocurren. Este trabajo pretende facilitar el acceso a este recurso básico de la programación.
DEFINICIONES
Voy a establecer de entrada algunas definiciones:
VARIABLE
Nombre asignado a un espacio en la memoria del dispositivo para guardar un dato que va a ser usado en alguna fase del programa o Proyecto.
Se identifica en Tasker porque va precedido por el símbolo %. Escrito con alguna letra en mayúsculas (%Variable, o %variaBle) tiene el carácter de variable global y puede recuperarse su contenido desde cualquier tarea del proyecto o de otros proyectos dentro de Tasker. Se almacena como datos del programa.
Si su nombre no contiene ninguna mayúscula (p.e. %temporal) es una variable local de la tarea en donde se le ha asignado un valor pero, al salir de esta tarea, se pierde el contenido y, incluso, el nombre de la variable.
El valor guardado en las variables de los dos tipos anteriores (variables de usuario) puede ser un número entero, un número decimal, una cadena de caracteres o una mezcla de todo lo anterior. En el límite, podriamos guardar toda la novela "El ingenioso hidalgo don Quijote de la Mancha" en una sola variable que podriamos llamar, acertadamente, como %Quijote. A este respecto es recomendable que el nombre de la variable, si se puede, indique de alguna manera su contenido.
Variable de Sistema es una variable que proporciona Tasker y en la que se guarda algún valor que facilita el propio sistema Android. Por ejemplo $DATE contiene la fecha de hoy, %TIME la hora actual, %LOC las coordenadas obtenidas con GPS, etc. Podemos usarlas y operar con ellas pero generalmente, con algunas excepciones, no podremos modificarlas.
Una variable de usuario (global o local), como se ha dicho, puede contener cifras, letras, caracteres sueltos, frases completas y una mezcla de todo. Un ejemplo: creamos una variable que llamaré %fulano y en la que, mediante una acción Establecer Variable escribo: Martínez|Pérez|Luis|12-03-1975|Barcelona. De momento tengo UN sólo dato, una variable que contiene distintas "cosas"...
MATRIZ LINEAL
Tasker nos facilita un instrumento para extraer los datos de variables que, como %fulano, se han "preparado" convenientemente para convertirlas en lo que llamaremos una Matriz lineal. Esta acción "mágica" es "Separar Variable" y lo que hace es dividir el contenido de la variable de entrada (%fulano) mediante un carácter especial: el Separador (aquí el "|"). El resultado de la extracción son (ahora si) variables independientes que llamaremos "hijas" de %fulano. Estas variables hijas podremos identificarlas y operar con ellas separadamente como variables que son. El número de "hijas" será igual al número de separadores + 1.
¿Y como nos referiremos a ellas o recuperaremos su valor? pues por su índice dentro de la matriz lineal: %fulano(1)= Martínez, %fulano(2)=Pérez, %fulano(3)=Luis, %fulano(4)=12-03-1975 y %fulano(%)=Barcelona o más simplemente: %fulano1, %fulano2, %fulano3, %fulano4 y %fulano5.
Como antes y como variables que son, pueden ser globales (alguna letra mayúscula) o locales (todo en minúscula) según la "vida" y uso que deban tener. Si la variable inicial es global las hijas seran variables globales. Si es local las hijas serán locales.
En resumen, podemos concatenar (unir o enlazar) datos de distinto tipo en una sola variable que los contiene (%fulano, en el ejemplo) utilizando un carácter separador distintivo que utilizaremos para recuperarlas.
Al "fabricar" con los datos la variable de inicio elegimos el carácter separador que luego utilizaremos para obtener sus elementos individuales. Evidentemente para este fin eligiremos un carácter que no aparezca en ninguno de los datos, de lo contrario la acción Separar Variable nos podria cortar la variable %fulano por donde no esperamos.
Otra cosa: al separar la variable se pierde el separador utilizado, desaparece.
MATRIZ DE DOS DIMENSIONES
Vamos a escribir en una variable (Establecer Variable) un conjunto de datos (numéricos, alfanuméricos o combinación de ambos) usando DOS caracteres (& $ |! # u otro) separadores.
Ejemplo: Podemos construir una tabla de dos dimensiones (filas y columnas, como en una hoja de Excel) en la variable %Nombres que contiene los siguientes datos: José;Juan;Luisa;Antonio#Juan;Elena;Iñaki#Maria;Ped ro;Regina#Luis;José;Alberto;Maria José;Martina (Atentos: de momento tengo una sola variable con dos tipos de caracteres incrustados ";" y "#")
Mediante la acción "Separar Variable" sobre la variable %Nombres con el separador # obtendremos una matriz (lineal) con quatro variables que serán:
%Nombres1 = José;Juan;Luisa;Antonio
%Nombres2 = Juan;Elena;Iñaki
%Nombres3 = Maria;Pedro;Regina
%Nombres4 = Luis;José;Alberto;Maria José;Martina
(he puesto intencionadamente cantidades diferentes de nombres en cada grupo...)
Si aplicamos de nuevo la acción separar variable sobre la primera de las variables llamadas "hijas" de la matriz: %Nombres1, ahora con el separador ";" obtendremos las variables "nietas":
%Nombres11 = José
%Nombres12 = Juan
%Nombres13 = Luisa
%Nombres14 = Antonio
El índice 11 indica que %Nombres11 es la 1ª hija de la 1ª hija (la 1ªnieta de %Nombres, pues)
El indice 12 indica que %Nombres12 es la 2ª hija de la 1ª hija (la 2ªnieta)...
Igualmente podemos hacerlo sobre %Nombres2 para obtener los valores:
%Nombres21 = Juan
%Nombres22 = Elena
%Nombres23 = Iñaki
Y, de la misma manera, sobre %Nombres3 y %Nombres4
.............
Aquí yo ya me perdía cuando lei la traducción del manual original de Tasker...!
.............
Este procedimiento es el sistema ortodoxo (del manual) pero tiene algunos inconvenientes que complican su comprensión y utilización:
- Si hay más de 9 "hijas", al extraer las "nietas" los índices numéricos se entremezclan (¿ %Nombres123 es la nieta 3 de %Nombres12 o la hija 123 de %Nombres o la nieta 23 de %Nombres1?)
- La variable global %Nombres (antes de separar sus elementos la primera vez para generar la matriz) se mantiene al descomponerla. Así pues, además de la variable original que lo contiene todo, tendremos las hijas y las nietas, todas ellas globales. En resumen: un monton de datos guardados 3 veces en la memoria.
Y si la matriz tiene 3 dimensiones me van a aparecer "biznietas"!
¿Como resuelvo esto?
Una manera muy intuitiva y práctica es mediante el empleo de variables locales y matrices locales. En realidad, pocas veces necesitamos extraer todos los datos de una matriz de dos dimensiones (como almacén de variables), normalmente necesitamos acceder a los datos para consultar uno sólo (nieta) o a los de una sola fila de la tabla (hija).
Para ello expongo el sigüiente
EJEMPLO PRÁCTICO
Supongamos que tenemos un tren con 8 vagones y en cada uno de los cuales hay 50 asientos.
Construimos una variable (%Tren) que contiene, separados por # la lista de los nombres y apellidos de los pasajeros que viajan en cada vagón. Los nombres de los pasajeros los separaré con ;
Esta variable (que no matriz, de momento!) podria escribirse así:
José Pérez;Juan García...;Pedro Matas#Alberto Ruiz; ;......;Luis Gómez;Josefa Antón#Carlos Fuentes;Juan Galdós;...Antonio Durán#Elisa Jiménez;Maria de la Hoz;...#... (Bién, ya lo habeis entendido, no me hagaís inventar más nombres...!)
Fijaros que después de Alberto Ruiz hay un asiento vacio que ha quedado escrito entre separadores así ; ; (no lo pongo para marear la perdiz, los trenes no van siempre llenos!)
PROBLEMA 1: ¿Qué pasajero ocupa el asiento número 2 del vagón 3?
Vamos a copiar el contenido de la Variable global %Tren en una variable local %vagon:
Establecer variable %vagon A %Tren
Y generamos la matriz %vagon:
Separar Variable %vagon separador: #
¿Resultado?: Una matriz local cuyos elementos són la lista de los pasajeros de cada vagón. Así:
%vagon1 contiene José Pérez;Juan García;...;Pedro Matas
%vagon2 contiene Alberto Ruiz; ;......;Luis Gómez;Josefa Antón
%vagon3 contiene Carlos Fuentes;Juan García;...;Antonio Durán
etc...
Podemos extraer los nombres de todos los pasajeros del %vagon3 de esta manera:
Establecer variable %pasajero A %vagon3
Separar variable %pasajero separador ; (Extraemos los nombres de los pasajeros del %vagon3 obteniendo %pasajero1,%pasajero2;%pasajero3...)
El nombre del pasajero número 2 del vagón 3 es Juan García!
Este nombre lo podemos copiar a una variable global %Nombre_pasajero para que pueda ser utilizado en la tarea que requirió quién era el pasajero del asiento nº 2 del 3er vagón .(Podemos devolverlo como variable local, pero de momento lo dejamos aquí. Podeis consultar documentación específica sobre el uso de Tareas y Subtareas en este artículo de Caravantes: http://www.htcmania.com/showthread.php?t=744076)
Recapitulando, hemos superado los dos inconvenientes enunciados anteriormente:
- No hay índices de "hijas" y "nietas" mezclados.
- Usamos variables locales y matrices locales. Por tanto, al finalizar la tarea, se recupera el espacio de memoria que ocupaban. Sólo se mantiene la variable global %Tren y la que hemos creado %Nombre_pasajero que es reutilizable...
Problema: ¿como lo escribimos en Tasker?
Datos: %Tren = Lista de pasajeros del tren separados por ; y con un caracter # separando los vagones.
Busco, como en el ejemplo, el pasajero 2 del vagón 3
Desde la tarea que necesita el nombre ejecutamos la subtarea que nos lo proporcionará y que llamo Nombre Del Pasajero
Acción Ejecutar tarea: Nombre Del Pasajero %par1=2 %par2=3 (%par1 = asiento del pasajero %par2 número del vagón)
La tarea Nombre Del Pasajero será así:
Nombre Del Pasajero (22)
A1: Establecer variable [ Nombre:%vagon A:%Tren Calcular:Apagado Añadir:Apagado ] (copio la variable global %Tren a la variable local %vagon)
A2: Separar variable [ Nombre:%vagon Separador:# Eliminar base:Apagado ]
(genero la matriz %vagon cuyas hijas %vagon1,%vagon2... son las listas de pasajeros de cada vagon)
A3: Establecer variable [ Nombre:%pasajero A:%vagon(%par2) Calcular:Apagado Añadir:Apagado ]
(copio la lista de pasajeros del vagon que me interesa %par2=3 a una variable local %pasajero)
A4: Separar variable [ Nombre:%pasajero Separador:; Eliminar base:Apagado ] (genero la matriz %pasajero cuyas hijas son los nombres de cada pasajero)
A5: Establecer variable [ Nombre:%Nom_pasaj A:%pasajero(%par1) Calcular:Apagado Añadir:Apagado ]
(copio el nombre del pasajero que ocupa el lugar %par1=2 a la variable global %Nom_pasaj que necesita la tarea que me lo ha pedido)
<<H1><font color = green> Filtro para CASOS ESPECIALES>
(etiqueta en color y con caracteres grandes que me indica para que sirve lo que viene a continuación y que... leedlo, se entiende fácil!)
A6: Establecer variable [ Nombre:%Nom_pasaj A:Asiento libre Calcular:Apagado Añadir:Apagado ] Si (if) [ %Nom_pasaj ~ %pas+ ]
A7: Establecer variable [ Nombre:%Nom_pasaj A:Asiento libre Calcular:Apagado Añadir:Apagado ] Si (if) [ %Nom_pasaj !~ ++ ]
A8: Establecer variable [ Nombre:%Nom_pasaj A:No existe el asiento %Asiento Calcular:Apagado Añadir:Apagado ] Si (if) [ %Asiento > 50 ]
A9: Establecer variable [ Nombre:%Nom_pasaj A:No existe el vagon %Vagon Calcular:Apagado Añadir:Apagado ] Si (if) [ %Vagon > 8 ]PROBLEMA 2: ¿Que número de asiento ocupa y en que vagon está el pasajero Josefa Antón?
Datos: %Tren y %Pasajero (Josefa Antón en este caso)
Desde la tarea que necesita el número de asiento y de vagón llamamos a la subtarea que nos lo proporcionará Tarea y que he llamado "Numero De Asiento"
Acción Ejecutar tarea "Numero De Asiento" %par1=%Pasajero %par2=vacio
La tarea Numero De Asiento hará esto, en lenguaje de Tasker y sangrando el texto en los bucles anidados:
Numero De Asiento (64)
A1: Establecer variable [ Nombre:%vagon A:%Tren Calcular:Apagado Añadir:Apagado ]
A2: Separar variable [ Nombre:%vagon Separador:# Eliminar base:Apagado ]
A3: Establecer variable [ Nombre:%cont_vagon A:0 Calcular:Apagado Añadir:Apagado ]
A4: For [ Variable:%pasajeros Ítems:%vagon(:) ]
A5: Sumar a variable [ Nombre:%cont_vagon Valor:1 Módulo (wrap around):0 ]
A6: Establecer variable [ Nombre:%cont_pasaj A:0 Calcular:Apagado Añadir:Apagado ]
A7: Separar variable [ Nombre:%pasajeros Separador:; Eliminar base:Apagado ]
A8: For [ Variable:%temporal Ítems:%pasajeros(:) ]
A9: Sumar a variable [ Nombre:%cont_pasaj Valor:1 Módulo (wrap around):0 ]
A10: Ir a acción [ Tipo:Etiqueta Acción Número:1 Etiqueta:Ya Te Tengo ] Si (if) [ %temporal ~ %par1 ]
A11: End For
A12: End For
A13: Flash [ Texto:Pasajero no encontrado… Largo:Apagado ]
A14: Detener [ Con error:Apagado Tarea: ]
<Ya Te Tengo>
A15: Destino (de goto)
A16: Establecer variable [ Nombre:%Asiento A:%cont_pasaj Calcular:Apagado Añadir:Apagado ]
A17: Establecer variable [ Nombre:%Vagon AEn castellano más o menos corriente:
A1 - copiar el contenido de la variable global %Tren a la variable local %vagon
A2 - generar la matriz %vagon cuyas hijas %vagon1,%vagon2... son las listas completas de pasajeros de cada vagon>
A3 - poner a 0 el contador de vagones: %cont_vagon
A4 - mediante un bucle FOR buscar exhaustivamente el nombre del pasajero Josefa Antón (%par1) en la lista de nombres de cada vagón
A5 - empieza con %vagon1
A6 - por si ha hecho todo el bucle y no ha encontrado el nombre en un vagón, pone el contador de asientos a 0 antes de empezar con el sigüiente.
A7 - genera la matriz que contiene la lista de pasajeros del vagón
A8 - inicia el bucle para comparar el nombre %par1 con los de las lista
A9 - y incrementa el contador de pasajeros
A10 - si el nombre de la lista coincide con %par1, vete a la etiqueta (goto) Ya Te Tengo
A11 - acaba el bucle dentro del vagón y como no ha encontrado el nombre (si lo hubiera encontrado habria saltado a la etiqueta)...
A12 - vuelve al primer bucle, donde incrementa %cont_vagon y busca en el vagón sigüiente.
A13 - si se acaban los vagones: Flash "Pasajero no encontrado"
A14 - y se acaba la Tarea
A15 - peeeeeero, si lo ha encontrado...
A16 - copia a la variable %Asiento el valor %cont_pasaj
A17 - y en %Vagon el valor de %cont_vagon en el momento que ha encontrado a Josefa Antón.
La tarea es muy básica pero funciona. Deberia completarse para ofrecer solución a dos problemas que, de entrada, se me ocurren: ¿que pasa si hay dos pasajeros con igual nombre y apellido?. ¿Como podria saber el número de asientos libres?... Lo dejo como ejercicio para nota...!
MALDITO TECLADO!
Si tenemos que cargar una matriz con un número de datos importante (en el ejemplo propuesto habria 8x50=400 nombres y apellidos) se nos presenta un problema: vamos a pasarnos un buen rato tecleando datos, repasándolos y rectificando posibles errores con un teclado de la Srta. Pepis...
Al mismo tiempo muchas veces ya tenemos (o podemos tener) estos datos en una tabla de Excel. Esto facilita mucho el trabajo de leer los datos y meterlos en una variable. ¿Cómo? Voy a exponer como lo hago yo.
Suponemos pues que ya tenemos los datos en una hoja de cálculo en Excel. Una tabla con filas y columnas que deberemos preparar así:
1 - Eliminamos encabezamiento de columnas (títulos), colores, etc. dejando la tabla limpia. Si queremos conservar la original podemos hacer una copia con otro nombre. Es aconsejable eliminar también los libros 2 y 3 que, por defecto, nos coloca Excel.
2 - Eliminamos los puntos separadores de miles seleccionando todos los campos de la hoja y, en Formato, desactivar el separador de miles.
3 - Luego, en "Archivo", seleccionamos "Guardar como" con la opción "Archivo separado por comas (csv)"
4 - Una vez guardado el archivo salimos de excel y lo enviamos por correo a nuestra propia dirección para tenerlo en el teléfono.
5 - Ya desde el teléfono abrimos el correo y guardamos el archivo donde lo hacemos normalmente.
6 - Abrimos Tasker y nos creamos una pequeña tarea con una sola acción Leer archivo a la variable que queramos (%Tren en el ejemplo) y, que si vamos justos de memoria RAM puede ser incluso una variable local... (podria ser %tren en el ejemplo), indicando la ruta del archivo.
7 - Excel inserta saltos de línea al final de cada fila de datos. Para eliminarlos (hay otros métodos) yo lo hago así: Variable %Tren Buscar y reemplazar Buscar /n Reemplazar con #
8 - Como Excel separa los datos con ; ya tenemos el separador de datos dentro de cada fila (nombres). El separador de columnas (vagones) será #
9 - IMPORTANTE Como Excel, por defecto, utiliza como separador de decimales la coma "," mediante un nuevo Variable > Buscar y reemplazar , por . tendremos que los datos numéricos con decimales ya serán operables con Tasker.
MATRICES DE TRES DIMENSIONES
No voy a entrar en ello, lo voy a dejar como una reflexión en caliente solamente: Si en lugar de los nombres hubiera escrito en %Tren una variable como la que he creado al principio del artículo %fulano conteniendo Martínez|Pérez|Luis|12-03-1975|Barcelona, podria extraer los datos de cada pasajero mediante una acción Separar Variable utilizando el separador |. Tendria una matriz de tres dimensiones!
A partir de estos datos podria realizar tareas que respondieran a preguntas del tipo: ¿Que dia nació el pasajero que ocupa el asiento x del Vagón Y? ¿Cuantos Pasajeros de llaman Luís? o ¿Cuantos residen en San Sebastián?...
CONCLUSIÓN
En el transcurso de la lectura de este artículo, si habeis sido pacientes y habeis llegado hasta aquí, es muy probable que ya se os haya ocurrido alguna idea para realizar un programa que os sea útil. Muchos de nosotros usamos hojas de cálculo de Excel: listas de precios por modelos y tamaños, tablas de calificaciones (con los alumnos en filas y las distintas asignaturas en columnas de la que se pueden extraer medias, notas máximas, listas de suspensos...), horarios de autobuses según destinos, etc. hay un mundo entero de datos en hojas de cálculo en Internet. Tampoco se trata de crear una base de datos como la de la SS, pero seguro que se os ocurren aplicaciones.
A mí se me está metiendo en la cabeza la idea (mucho más abstracta) de hacer una tarea multipropósito para gestionar la consulta de datos de variables preparadas para convertirse en matrices de dos dimensiones. Tal vez sea mi próximo proyecto.
Bueno, lo dejo para más adelante, ahora sólo se me ocurre añadir una cosa: Pasajeros, al tren!
AÑADIDO: Referencia donde Caravantes proporciona un método para evitar caracteres "raros" en los archivos extraidos de Excel:
Interesantísimo, como siempre, muchas gracias.
Respecto al bug de los caracteres especiales... Supongo que sabes que el juego de caracteres ASCII básico (128 caracteres) nunca da problemas... pero eso no incluye ningún carácter acentuado ni eñes, etc. Para añadir esos otros caracteres especiales se inventaron otros sistemas de codificación más complejos, el problema es que no hay unanimidad en su uso. Por defecto, Windows codifica con el sistema ISO 8859-1 (europeo occidental), pero Android usa otro sistema. ¿Cuál?
Yo lo descubrí haciendo la operación inversa. Utilizando Tasker, generé un archivo TXT que contuviera caracteres especiales. Luego llevé ese archivo a Windows y lo abrí con Word. En ese momento, Word abrió una ventana para que yo indicase cuál era la codificación adecuada; podía ir probando con los diferentes sistemas de codificación y viendo una "vista rápida" del resultado. De esa forma comprobé que la codificación correcta era UNICODE UTF-8.
Ahora viene la segunda parte: Cómo generar (en Windows) un archivo con esa codificación, para que funcione bien en Android. Abres el fichero con el Word. Eliges ARCHIVO > GUARDAR-CÓMO. Seleccionas el tipo TEXTO SIN FORMATO, y le das a GUARDAR. Aparecerá otra ventana en la que podrás especificar el sistema de codificación; eliges OTRA-CODIFICACIÓN y luego UNICODE UTF-8. El fichero así generado funcionará perfectamente en Android, incluyendo sus caracteres especiales.
Más detalles e información en las páginas siguientes
Codificación de caracteres
http://es.wikipedia.org/wiki/Codific..._de_caracteres (http://es.wikipedia.org/wiki/Codificaci%C3%B3n_de_caracteres)
Elegir la codificación de texto al abrir y guardar archivos
http://office.microsoft.com/es-es/su...010121249.aspx (http://office.microsoft.com/es-es/support/elegir-la-codificacion-de-texto-al-abrir-y-guardar-archivos-HA010121249.aspx)
Luego, con el desarrollo de un par de Proyectos que incluian y manejaban bases de datos, he visto que, una vez le has cogido el tranquillo y has leido Proyectos tan elaborados y complejos como, por ejemplo, el de mlsir (Whatsapp sin manos), realmente SI que podemos llamarlas matrices. Construidas de otro modo, de acuerdo, pero matrices al fin y al cabo.
De todas formas me viene a la cabeza un chiste del recordado Eugenio que decia, después del Ya sabeis aquel..:
Se encuentran dos amigos y uno le dice al otro:
¿Como lo haces para conservarte tan joven?
Pues no discutiendo con nadie!
Por eso no será...
Bueno, pues no será por eso...
Así que, si quereis, podeis llamarlas Matrices, Arrays o Arreglos (así no, por favor!)
Por mi parte, como estoy acostumbrado a llamarlas Matrices, voy a usar este nombre a lo largo de este trabajo. Además tiene otra acepción en el diccionario: "Entidad generadora de otras" que se ajusta exactamente a lo que son como vereis más adelante.
OBJETIVO DEL TRABAJO
El objetivo fijado es allanar la comprensión de conceptos básicos sobre las variables (para los que empiezan o no se atreven con ellas) y facilitar estructuras simples de creación, manipulación y procesamiento de matrices de datos con ejemplos ilustrativos. El disponer de un almacén de datos es esencial para muchos de los programas que se nos ocurren. Este trabajo pretende facilitar el acceso a este recurso básico de la programación.
DEFINICIONES
Voy a establecer de entrada algunas definiciones:
VARIABLE
Nombre asignado a un espacio en la memoria del dispositivo para guardar un dato que va a ser usado en alguna fase del programa o Proyecto.
Se identifica en Tasker porque va precedido por el símbolo %. Escrito con alguna letra en mayúsculas (%Variable, o %variaBle) tiene el carácter de variable global y puede recuperarse su contenido desde cualquier tarea del proyecto o de otros proyectos dentro de Tasker. Se almacena como datos del programa.
Si su nombre no contiene ninguna mayúscula (p.e. %temporal) es una variable local de la tarea en donde se le ha asignado un valor pero, al salir de esta tarea, se pierde el contenido y, incluso, el nombre de la variable.
El valor guardado en las variables de los dos tipos anteriores (variables de usuario) puede ser un número entero, un número decimal, una cadena de caracteres o una mezcla de todo lo anterior. En el límite, podriamos guardar toda la novela "El ingenioso hidalgo don Quijote de la Mancha" en una sola variable que podriamos llamar, acertadamente, como %Quijote. A este respecto es recomendable que el nombre de la variable, si se puede, indique de alguna manera su contenido.
Variable de Sistema es una variable que proporciona Tasker y en la que se guarda algún valor que facilita el propio sistema Android. Por ejemplo $DATE contiene la fecha de hoy, %TIME la hora actual, %LOC las coordenadas obtenidas con GPS, etc. Podemos usarlas y operar con ellas pero generalmente, con algunas excepciones, no podremos modificarlas.
Una variable de usuario (global o local), como se ha dicho, puede contener cifras, letras, caracteres sueltos, frases completas y una mezcla de todo. Un ejemplo: creamos una variable que llamaré %fulano y en la que, mediante una acción Establecer Variable escribo: Martínez|Pérez|Luis|12-03-1975|Barcelona. De momento tengo UN sólo dato, una variable que contiene distintas "cosas"...
MATRIZ LINEAL
Tasker nos facilita un instrumento para extraer los datos de variables que, como %fulano, se han "preparado" convenientemente para convertirlas en lo que llamaremos una Matriz lineal. Esta acción "mágica" es "Separar Variable" y lo que hace es dividir el contenido de la variable de entrada (%fulano) mediante un carácter especial: el Separador (aquí el "|"). El resultado de la extracción son (ahora si) variables independientes que llamaremos "hijas" de %fulano. Estas variables hijas podremos identificarlas y operar con ellas separadamente como variables que son. El número de "hijas" será igual al número de separadores + 1.
¿Y como nos referiremos a ellas o recuperaremos su valor? pues por su índice dentro de la matriz lineal: %fulano(1)= Martínez, %fulano(2)=Pérez, %fulano(3)=Luis, %fulano(4)=12-03-1975 y %fulano(%)=Barcelona o más simplemente: %fulano1, %fulano2, %fulano3, %fulano4 y %fulano5.
Como antes y como variables que son, pueden ser globales (alguna letra mayúscula) o locales (todo en minúscula) según la "vida" y uso que deban tener. Si la variable inicial es global las hijas seran variables globales. Si es local las hijas serán locales.
En resumen, podemos concatenar (unir o enlazar) datos de distinto tipo en una sola variable que los contiene (%fulano, en el ejemplo) utilizando un carácter separador distintivo que utilizaremos para recuperarlas.
Al "fabricar" con los datos la variable de inicio elegimos el carácter separador que luego utilizaremos para obtener sus elementos individuales. Evidentemente para este fin eligiremos un carácter que no aparezca en ninguno de los datos, de lo contrario la acción Separar Variable nos podria cortar la variable %fulano por donde no esperamos.
Otra cosa: al separar la variable se pierde el separador utilizado, desaparece.
MATRIZ DE DOS DIMENSIONES
Vamos a escribir en una variable (Establecer Variable) un conjunto de datos (numéricos, alfanuméricos o combinación de ambos) usando DOS caracteres (& $ |! # u otro) separadores.
Ejemplo: Podemos construir una tabla de dos dimensiones (filas y columnas, como en una hoja de Excel) en la variable %Nombres que contiene los siguientes datos: José;Juan;Luisa;Antonio#Juan;Elena;Iñaki#Maria;Ped ro;Regina#Luis;José;Alberto;Maria José;Martina (Atentos: de momento tengo una sola variable con dos tipos de caracteres incrustados ";" y "#")
Mediante la acción "Separar Variable" sobre la variable %Nombres con el separador # obtendremos una matriz (lineal) con quatro variables que serán:
%Nombres1 = José;Juan;Luisa;Antonio
%Nombres2 = Juan;Elena;Iñaki
%Nombres3 = Maria;Pedro;Regina
%Nombres4 = Luis;José;Alberto;Maria José;Martina
(he puesto intencionadamente cantidades diferentes de nombres en cada grupo...)
Si aplicamos de nuevo la acción separar variable sobre la primera de las variables llamadas "hijas" de la matriz: %Nombres1, ahora con el separador ";" obtendremos las variables "nietas":
%Nombres11 = José
%Nombres12 = Juan
%Nombres13 = Luisa
%Nombres14 = Antonio
El índice 11 indica que %Nombres11 es la 1ª hija de la 1ª hija (la 1ªnieta de %Nombres, pues)
El indice 12 indica que %Nombres12 es la 2ª hija de la 1ª hija (la 2ªnieta)...
Igualmente podemos hacerlo sobre %Nombres2 para obtener los valores:
%Nombres21 = Juan
%Nombres22 = Elena
%Nombres23 = Iñaki
Y, de la misma manera, sobre %Nombres3 y %Nombres4
.............
Aquí yo ya me perdía cuando lei la traducción del manual original de Tasker...!
.............
Este procedimiento es el sistema ortodoxo (del manual) pero tiene algunos inconvenientes que complican su comprensión y utilización:
- Si hay más de 9 "hijas", al extraer las "nietas" los índices numéricos se entremezclan (¿ %Nombres123 es la nieta 3 de %Nombres12 o la hija 123 de %Nombres o la nieta 23 de %Nombres1?)
- La variable global %Nombres (antes de separar sus elementos la primera vez para generar la matriz) se mantiene al descomponerla. Así pues, además de la variable original que lo contiene todo, tendremos las hijas y las nietas, todas ellas globales. En resumen: un monton de datos guardados 3 veces en la memoria.
Y si la matriz tiene 3 dimensiones me van a aparecer "biznietas"!
¿Como resuelvo esto?
Una manera muy intuitiva y práctica es mediante el empleo de variables locales y matrices locales. En realidad, pocas veces necesitamos extraer todos los datos de una matriz de dos dimensiones (como almacén de variables), normalmente necesitamos acceder a los datos para consultar uno sólo (nieta) o a los de una sola fila de la tabla (hija).
Para ello expongo el sigüiente
EJEMPLO PRÁCTICO
Supongamos que tenemos un tren con 8 vagones y en cada uno de los cuales hay 50 asientos.
Construimos una variable (%Tren) que contiene, separados por # la lista de los nombres y apellidos de los pasajeros que viajan en cada vagón. Los nombres de los pasajeros los separaré con ;
Esta variable (que no matriz, de momento!) podria escribirse así:
José Pérez;Juan García...;Pedro Matas#Alberto Ruiz; ;......;Luis Gómez;Josefa Antón#Carlos Fuentes;Juan Galdós;...Antonio Durán#Elisa Jiménez;Maria de la Hoz;...#... (Bién, ya lo habeis entendido, no me hagaís inventar más nombres...!)
Fijaros que después de Alberto Ruiz hay un asiento vacio que ha quedado escrito entre separadores así ; ; (no lo pongo para marear la perdiz, los trenes no van siempre llenos!)
PROBLEMA 1: ¿Qué pasajero ocupa el asiento número 2 del vagón 3?
Vamos a copiar el contenido de la Variable global %Tren en una variable local %vagon:
Establecer variable %vagon A %Tren
Y generamos la matriz %vagon:
Separar Variable %vagon separador: #
¿Resultado?: Una matriz local cuyos elementos són la lista de los pasajeros de cada vagón. Así:
%vagon1 contiene José Pérez;Juan García;...;Pedro Matas
%vagon2 contiene Alberto Ruiz; ;......;Luis Gómez;Josefa Antón
%vagon3 contiene Carlos Fuentes;Juan García;...;Antonio Durán
etc...
Podemos extraer los nombres de todos los pasajeros del %vagon3 de esta manera:
Establecer variable %pasajero A %vagon3
Separar variable %pasajero separador ; (Extraemos los nombres de los pasajeros del %vagon3 obteniendo %pasajero1,%pasajero2;%pasajero3...)
El nombre del pasajero número 2 del vagón 3 es Juan García!
Este nombre lo podemos copiar a una variable global %Nombre_pasajero para que pueda ser utilizado en la tarea que requirió quién era el pasajero del asiento nº 2 del 3er vagón .(Podemos devolverlo como variable local, pero de momento lo dejamos aquí. Podeis consultar documentación específica sobre el uso de Tareas y Subtareas en este artículo de Caravantes: http://www.htcmania.com/showthread.php?t=744076)
Recapitulando, hemos superado los dos inconvenientes enunciados anteriormente:
- No hay índices de "hijas" y "nietas" mezclados.
- Usamos variables locales y matrices locales. Por tanto, al finalizar la tarea, se recupera el espacio de memoria que ocupaban. Sólo se mantiene la variable global %Tren y la que hemos creado %Nombre_pasajero que es reutilizable...
Problema: ¿como lo escribimos en Tasker?
Datos: %Tren = Lista de pasajeros del tren separados por ; y con un caracter # separando los vagones.
Busco, como en el ejemplo, el pasajero 2 del vagón 3
Desde la tarea que necesita el nombre ejecutamos la subtarea que nos lo proporcionará y que llamo Nombre Del Pasajero
Acción Ejecutar tarea: Nombre Del Pasajero %par1=2 %par2=3 (%par1 = asiento del pasajero %par2 número del vagón)
La tarea Nombre Del Pasajero será así:
Nombre Del Pasajero (22)
A1: Establecer variable [ Nombre:%vagon A:%Tren Calcular:Apagado Añadir:Apagado ] (copio la variable global %Tren a la variable local %vagon)
A2: Separar variable [ Nombre:%vagon Separador:# Eliminar base:Apagado ]
(genero la matriz %vagon cuyas hijas %vagon1,%vagon2... son las listas de pasajeros de cada vagon)
A3: Establecer variable [ Nombre:%pasajero A:%vagon(%par2) Calcular:Apagado Añadir:Apagado ]
(copio la lista de pasajeros del vagon que me interesa %par2=3 a una variable local %pasajero)
A4: Separar variable [ Nombre:%pasajero Separador:; Eliminar base:Apagado ] (genero la matriz %pasajero cuyas hijas son los nombres de cada pasajero)
A5: Establecer variable [ Nombre:%Nom_pasaj A:%pasajero(%par1) Calcular:Apagado Añadir:Apagado ]
(copio el nombre del pasajero que ocupa el lugar %par1=2 a la variable global %Nom_pasaj que necesita la tarea que me lo ha pedido)
<<H1><font color = green> Filtro para CASOS ESPECIALES>
(etiqueta en color y con caracteres grandes que me indica para que sirve lo que viene a continuación y que... leedlo, se entiende fácil!)
A6: Establecer variable [ Nombre:%Nom_pasaj A:Asiento libre Calcular:Apagado Añadir:Apagado ] Si (if) [ %Nom_pasaj ~ %pas+ ]
A7: Establecer variable [ Nombre:%Nom_pasaj A:Asiento libre Calcular:Apagado Añadir:Apagado ] Si (if) [ %Nom_pasaj !~ ++ ]
A8: Establecer variable [ Nombre:%Nom_pasaj A:No existe el asiento %Asiento Calcular:Apagado Añadir:Apagado ] Si (if) [ %Asiento > 50 ]
A9: Establecer variable [ Nombre:%Nom_pasaj A:No existe el vagon %Vagon Calcular:Apagado Añadir:Apagado ] Si (if) [ %Vagon > 8 ]PROBLEMA 2: ¿Que número de asiento ocupa y en que vagon está el pasajero Josefa Antón?
Datos: %Tren y %Pasajero (Josefa Antón en este caso)
Desde la tarea que necesita el número de asiento y de vagón llamamos a la subtarea que nos lo proporcionará Tarea y que he llamado "Numero De Asiento"
Acción Ejecutar tarea "Numero De Asiento" %par1=%Pasajero %par2=vacio
La tarea Numero De Asiento hará esto, en lenguaje de Tasker y sangrando el texto en los bucles anidados:
Numero De Asiento (64)
A1: Establecer variable [ Nombre:%vagon A:%Tren Calcular:Apagado Añadir:Apagado ]
A2: Separar variable [ Nombre:%vagon Separador:# Eliminar base:Apagado ]
A3: Establecer variable [ Nombre:%cont_vagon A:0 Calcular:Apagado Añadir:Apagado ]
A4: For [ Variable:%pasajeros Ítems:%vagon(:) ]
A5: Sumar a variable [ Nombre:%cont_vagon Valor:1 Módulo (wrap around):0 ]
A6: Establecer variable [ Nombre:%cont_pasaj A:0 Calcular:Apagado Añadir:Apagado ]
A7: Separar variable [ Nombre:%pasajeros Separador:; Eliminar base:Apagado ]
A8: For [ Variable:%temporal Ítems:%pasajeros(:) ]
A9: Sumar a variable [ Nombre:%cont_pasaj Valor:1 Módulo (wrap around):0 ]
A10: Ir a acción [ Tipo:Etiqueta Acción Número:1 Etiqueta:Ya Te Tengo ] Si (if) [ %temporal ~ %par1 ]
A11: End For
A12: End For
A13: Flash [ Texto:Pasajero no encontrado… Largo:Apagado ]
A14: Detener [ Con error:Apagado Tarea: ]
<Ya Te Tengo>
A15: Destino (de goto)
A16: Establecer variable [ Nombre:%Asiento A:%cont_pasaj Calcular:Apagado Añadir:Apagado ]
A17: Establecer variable [ Nombre:%Vagon AEn castellano más o menos corriente:
A1 - copiar el contenido de la variable global %Tren a la variable local %vagon
A2 - generar la matriz %vagon cuyas hijas %vagon1,%vagon2... son las listas completas de pasajeros de cada vagon>
A3 - poner a 0 el contador de vagones: %cont_vagon
A4 - mediante un bucle FOR buscar exhaustivamente el nombre del pasajero Josefa Antón (%par1) en la lista de nombres de cada vagón
A5 - empieza con %vagon1
A6 - por si ha hecho todo el bucle y no ha encontrado el nombre en un vagón, pone el contador de asientos a 0 antes de empezar con el sigüiente.
A7 - genera la matriz que contiene la lista de pasajeros del vagón
A8 - inicia el bucle para comparar el nombre %par1 con los de las lista
A9 - y incrementa el contador de pasajeros
A10 - si el nombre de la lista coincide con %par1, vete a la etiqueta (goto) Ya Te Tengo
A11 - acaba el bucle dentro del vagón y como no ha encontrado el nombre (si lo hubiera encontrado habria saltado a la etiqueta)...
A12 - vuelve al primer bucle, donde incrementa %cont_vagon y busca en el vagón sigüiente.
A13 - si se acaban los vagones: Flash "Pasajero no encontrado"
A14 - y se acaba la Tarea
A15 - peeeeeero, si lo ha encontrado...
A16 - copia a la variable %Asiento el valor %cont_pasaj
A17 - y en %Vagon el valor de %cont_vagon en el momento que ha encontrado a Josefa Antón.
La tarea es muy básica pero funciona. Deberia completarse para ofrecer solución a dos problemas que, de entrada, se me ocurren: ¿que pasa si hay dos pasajeros con igual nombre y apellido?. ¿Como podria saber el número de asientos libres?... Lo dejo como ejercicio para nota...!
MALDITO TECLADO!
Si tenemos que cargar una matriz con un número de datos importante (en el ejemplo propuesto habria 8x50=400 nombres y apellidos) se nos presenta un problema: vamos a pasarnos un buen rato tecleando datos, repasándolos y rectificando posibles errores con un teclado de la Srta. Pepis...
Al mismo tiempo muchas veces ya tenemos (o podemos tener) estos datos en una tabla de Excel. Esto facilita mucho el trabajo de leer los datos y meterlos en una variable. ¿Cómo? Voy a exponer como lo hago yo.
Suponemos pues que ya tenemos los datos en una hoja de cálculo en Excel. Una tabla con filas y columnas que deberemos preparar así:
1 - Eliminamos encabezamiento de columnas (títulos), colores, etc. dejando la tabla limpia. Si queremos conservar la original podemos hacer una copia con otro nombre. Es aconsejable eliminar también los libros 2 y 3 que, por defecto, nos coloca Excel.
2 - Eliminamos los puntos separadores de miles seleccionando todos los campos de la hoja y, en Formato, desactivar el separador de miles.
3 - Luego, en "Archivo", seleccionamos "Guardar como" con la opción "Archivo separado por comas (csv)"
4 - Una vez guardado el archivo salimos de excel y lo enviamos por correo a nuestra propia dirección para tenerlo en el teléfono.
5 - Ya desde el teléfono abrimos el correo y guardamos el archivo donde lo hacemos normalmente.
6 - Abrimos Tasker y nos creamos una pequeña tarea con una sola acción Leer archivo a la variable que queramos (%Tren en el ejemplo) y, que si vamos justos de memoria RAM puede ser incluso una variable local... (podria ser %tren en el ejemplo), indicando la ruta del archivo.
7 - Excel inserta saltos de línea al final de cada fila de datos. Para eliminarlos (hay otros métodos) yo lo hago así: Variable %Tren Buscar y reemplazar Buscar /n Reemplazar con #
8 - Como Excel separa los datos con ; ya tenemos el separador de datos dentro de cada fila (nombres). El separador de columnas (vagones) será #
9 - IMPORTANTE Como Excel, por defecto, utiliza como separador de decimales la coma "," mediante un nuevo Variable > Buscar y reemplazar , por . tendremos que los datos numéricos con decimales ya serán operables con Tasker.
MATRICES DE TRES DIMENSIONES
No voy a entrar en ello, lo voy a dejar como una reflexión en caliente solamente: Si en lugar de los nombres hubiera escrito en %Tren una variable como la que he creado al principio del artículo %fulano conteniendo Martínez|Pérez|Luis|12-03-1975|Barcelona, podria extraer los datos de cada pasajero mediante una acción Separar Variable utilizando el separador |. Tendria una matriz de tres dimensiones!
A partir de estos datos podria realizar tareas que respondieran a preguntas del tipo: ¿Que dia nació el pasajero que ocupa el asiento x del Vagón Y? ¿Cuantos Pasajeros de llaman Luís? o ¿Cuantos residen en San Sebastián?...
CONCLUSIÓN
En el transcurso de la lectura de este artículo, si habeis sido pacientes y habeis llegado hasta aquí, es muy probable que ya se os haya ocurrido alguna idea para realizar un programa que os sea útil. Muchos de nosotros usamos hojas de cálculo de Excel: listas de precios por modelos y tamaños, tablas de calificaciones (con los alumnos en filas y las distintas asignaturas en columnas de la que se pueden extraer medias, notas máximas, listas de suspensos...), horarios de autobuses según destinos, etc. hay un mundo entero de datos en hojas de cálculo en Internet. Tampoco se trata de crear una base de datos como la de la SS, pero seguro que se os ocurren aplicaciones.
A mí se me está metiendo en la cabeza la idea (mucho más abstracta) de hacer una tarea multipropósito para gestionar la consulta de datos de variables preparadas para convertirse en matrices de dos dimensiones. Tal vez sea mi próximo proyecto.
Bueno, lo dejo para más adelante, ahora sólo se me ocurre añadir una cosa: Pasajeros, al tren!
AÑADIDO: Referencia donde Caravantes proporciona un método para evitar caracteres "raros" en los archivos extraidos de Excel:
Interesantísimo, como siempre, muchas gracias.
Respecto al bug de los caracteres especiales... Supongo que sabes que el juego de caracteres ASCII básico (128 caracteres) nunca da problemas... pero eso no incluye ningún carácter acentuado ni eñes, etc. Para añadir esos otros caracteres especiales se inventaron otros sistemas de codificación más complejos, el problema es que no hay unanimidad en su uso. Por defecto, Windows codifica con el sistema ISO 8859-1 (europeo occidental), pero Android usa otro sistema. ¿Cuál?
Yo lo descubrí haciendo la operación inversa. Utilizando Tasker, generé un archivo TXT que contuviera caracteres especiales. Luego llevé ese archivo a Windows y lo abrí con Word. En ese momento, Word abrió una ventana para que yo indicase cuál era la codificación adecuada; podía ir probando con los diferentes sistemas de codificación y viendo una "vista rápida" del resultado. De esa forma comprobé que la codificación correcta era UNICODE UTF-8.
Ahora viene la segunda parte: Cómo generar (en Windows) un archivo con esa codificación, para que funcione bien en Android. Abres el fichero con el Word. Eliges ARCHIVO > GUARDAR-CÓMO. Seleccionas el tipo TEXTO SIN FORMATO, y le das a GUARDAR. Aparecerá otra ventana en la que podrás especificar el sistema de codificación; eliges OTRA-CODIFICACIÓN y luego UNICODE UTF-8. El fichero así generado funcionará perfectamente en Android, incluyendo sus caracteres especiales.
Más detalles e información en las páginas siguientes
Codificación de caracteres
http://es.wikipedia.org/wiki/Codific..._de_caracteres (http://es.wikipedia.org/wiki/Codificaci%C3%B3n_de_caracteres)
Elegir la codificación de texto al abrir y guardar archivos
http://office.microsoft.com/es-es/su...010121249.aspx (http://office.microsoft.com/es-es/support/elegir-la-codificacion-de-texto-al-abrir-y-guardar-archivos-HA010121249.aspx)