Return Multiple

Pregunta Sin Miedo no te cortes cualquier cosa para empezar - Autoit se comienza facilmente.Para Ordenes o Comandos sueltos. Ver nota como preguntar.
Responder
Pablo2m
Hacker del Foro
Mensajes: 88
Registrado: 28 May 2008, 21:16
Ubicación: Agentina

Return Multiple

Mensaje por Pablo2m »

Hola:
¿ Hay alguna forma que un Return devuelva un array ?, yo probe y no puede.

Lo mas cerca que llegue es

$paquete= $dato1&"*" &$dato2
Return $paquete

y luego usando un _StringExplode

Saludos
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Return Multiple

Mensaje por Chefito »

Pues claro. Pequeño ejemplo:

Código: Seleccionar todo

Func array()
	Dim $array[2]=["hola","adios"]
	Return $array
EndFunc
$miArray=array()
MsgBox(0,"",$miarray[0] & "," & $miarray[1])
Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Return Multiple

Mensaje por Ximorro »

Efectivamente, como puedes ver en el ejemplo de Chefito es perfectamente posible. No necesitas declarar la variable externa como array, de hecho tampoco sirve para nada porque será "machacada" con el array que crea la función.

Para ampliar la información, dado el título del post, hay otra manera de devolver valores múltiples: en parámetros por referencia en la función.
No es un método tan común pero a veces va bien, unas cuantas funciones de la librería Date.au3 usan este sistema, por ejemplo.
En este caso lo que se hace es modificar las variables que se pasan como parámetros, por ejemplo la llamada:
_DateTimeSplit("2005/01/01 14:30",$MyDate,$MyTime)
Parte el string y devuelve dos arrays, uno con la fecha y otro con la hora, pero los devuelve en los parámetros $MyDate y $MyTime que obligatoriamente deben ser variables.

Para usar este sistema cuando creéis la función hay que decir que el parámetro es por referencia, se hace con ByRef:

Código: Seleccionar todo

Func _MiFuncion($entrada, ByRef $salida)
  $salida = $entrada * 2
EndFunc
El ejemplo es un poco tonto pero por ver el mecanismo. Al usar la función es necesario que en ese segundo parámetro haya una variable, no puede ser una constante. Las variables ByRef las podéis modificar dentro de la función y esa modificación se propaga a la variable con la que se ha llamado:

Código: Seleccionar todo

Global $doble
_MiFuncion(10, $doble) ; $doble valdrá 20
Usando este mecanismo se pueden devolver varios valores a la vez, creando varios parámetros ByRef. Por ejemplo de esta manera se hace más cómodo devolver varias matrices, tal como hace _DateTimeSplit.
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
gna08
Hacker del Foro
Mensajes: 379
Registrado: 27 Sep 2008, 18:51
Ubicación: Cordoba, Argentina

Re: Return Multiple

Mensaje por gna08 »

Y mira en tremendo lio me meti :smt013 jajja..
puedo meter mas arrays dentro de mas arrays.. y retornar aun mas arrays.. voy a soñar con ellas :smt020 jaja

Código: Seleccionar todo

$vars = _cargar()

$datos = _instalar($vars)

MsgBox(64, "Jooo", $datos[0] & $datos[1] & $datos[2])

Func _cargar()
	Dim $array1[3]=["holaa", "chau", "me fui"] , $array2[3]=[1,3,5], $array3[3]=["a", "u", "3"], $ret[3]
	$ret[0] = $array1
	$ret[1] = $array2
	$ret[2] = $array3
	Return $ret
EndFunc

Func _instalar($Data)
	$matriz1 = $Data[0]
	$matriz2 = $Data[1]
	$matriz3 = $Data[2]

	For $i = 0 To UBound($matriz1)-1
		MsgBox(0, "Nivel 1 _ UBound: " & UBound($matriz1), "$matriz1[" & $i & "]: " & $matriz1[$i])
	Next

	For $i = 0 To UBound($matriz2)-1
		MsgBox(0, "Nivel 2 _ UBound: " & UBound($matriz2), "$matriz2[" & $i & "]: " & $matriz2[$i])
	Next

	For $i = 0 To UBound($matriz3)-1
		MsgBox(0, "Nivel 3 _ UBound: " & UBound($matriz3), "$matriz3[" & $i & "]: " & $matriz3[$i])
	Next
	Return $Data[2]
EndFunc
Es solo una ideailla.. :smt031 :smt031

P/D: no se pork ahora no puedo usar el formato au3 en el foro.. :smt017
Aunk no m Buskes, Seguro m enkontras!
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Return Multiple

Mensaje por Chefito »

Arrays conteniendo a otros arrays?? :smt011 .
Esto lo veo un mal uso de los arrays. Para hacer esto es preferible que devuelvas arrays multidimensionales. Liaras menos a la memoria, y el acceso a los datos seguro que será más rápido :smt023 .

Variando un poco tu ejemplo, podría salir este otro ejemplo :smt003 :

Código: Seleccionar todo

Func _cargar()
   Dim $array1[3][3]=[["holaa", "chau", "me fui"] , [1,3,5], ["a", "u", "3"]]
   Return $array1
EndFunc
Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Avatar de Usuario
gna08
Hacker del Foro
Mensajes: 379
Registrado: 27 Sep 2008, 18:51
Ubicación: Cordoba, Argentina

Re: Return Multiple

Mensaje por gna08 »

Chefito escribió:Arrays conteniendo a otros arrays?? :smt011 .
Esto lo veo un mal uso de los arrays. Para hacer esto es preferible que devuelvas arrays multidimensionales. Liaras menos a la memoria, y el acceso a los datos seguro que será más rápido :smt023 .

Variando un poco tu ejemplo, podría salir este otro ejemplo :smt003 :

Código: Seleccionar todo

Func _cargar()
   Dim $array1[3][3]=[["holaa", "chau", "me fui"] , [1,3,5], ["a", "u", "3"]]
   Return $array1
EndFunc
Saludos.
si lo se.. era para mostrar algo nomas :O :smt021 jajaj y molestar un rato :smt028 aparte era viejo el post y ya estaba solucioado creo :smt021 sorry :smt020
Aunk no m Buskes, Seguro m enkontras!
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Return Multiple

Mensaje por Ximorro »

Bueno, tampoco creo que se pueda considerar mala programación tener arrays dentro de arrays, supongo que todo depende de lo que se esté haciendo, si por ejemplo quieres extraer el sub-array y tratarlo como tal tienes que tener arrays dentro de otros, de lo contrario sólo puedes acceder a los valores individuales.

Dicho esto, que quede claro que no es buena idea ponerse a meter arrays dentro de otros, si no hace falta no lo hagáis porque es un lío, para empezar no se puede acceder directamente a un elemento, es necesario extraer el subarray y entonces acceder al elemento en cuestión. Por eso si se va a manejar vectores completos sí puede ser interesante meterlos en arrays, pero si sólo se va a acceder a los elementos mejor arrays multidimensionados.
Nota: un vector es un array (matriz) de una dimensión, por simplificar las cosas, pero por supuesto se pueden tener matrices multidimensionales dentro de matrices multidimensionales... ¡¡con el correspondiente dolor de cabeza!!

Ejemplo de acceso:
Con matrices multidimensionales:

Código: Seleccionar todo

Global $a[3][3] = [[1,2,3], [4,5,6], [7,8,9]], $valor
$valor = $a[1][1] ;$valor vale 5
Con matrices dentro de matrices:

Código: Seleccionar todo

Global $b1[3] = [1,2,3], $b2[3] = [4,5,6], $b3[3] = [7,8,9]
Global $b[3] = [$b1, $b2, $b3], $valor
;;;;;$valor = $b[1][1] ; ¡¡Error, no se puede acceder así!!
$valor = $b[1] ;$valor es el vector completo [4,5,6]
$valor = $valor[1] ;$valor vale 5
Así que lógicamente el acceso a los elementos es mucho más fluido con matrices multidimensionales, pero el segundo metodo te permite recuperar el vector entero, y eso puede ser últil en un programa que maneje vectores, quizás te interese almacenarlos en matrices y entonces tendrías precisamente esa estructura, pero recordad, para obtener un elemento concreto de ese vector, primero es necesario sacarlo de la matriz.

Por supuesto en vez de vectores se pueden tener matrices de varias dimensiones, pero hay que estar realmente necesitado de estructuras muy complejas para necesitar algo así, si podéis estructurarlo de otra manera mejor, más que nada por salvaguardar vuestra salud mental ;-)
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Avatar de Usuario
Chefito
Profesional del Autoit
Mensajes: 2035
Registrado: 21 Feb 2008, 18:42
Ubicación: Albacete/Cuenca (España)

Re: Return Multiple

Mensaje por Chefito »

Sí, tienes razón. Me faltó especificar que justamente en el caso (su código) que me había puesto de ejemplo era una mala opción, ya que se podía hacer más ordenado con una matriz multidimensional.

Como bien dices, si se puede utilizar para almacenar varios vectores, pero casi prefiero hacer los vectores independientes que almacenarlos en otro vector :smt012 .

Nunca lo he hecho en AutoIt, pero a falta del tipo Estructura de datos, un vector que almacene varios tipos de datos.....entre ellos pudiendo ser otro vector, podría ser lo casi lo mismo que una Estructura de datos :smt002 .

Saludos.
Cita vista en algún lugar de la red: En este mundo hay 10 tipos de personas, los que saben binario y los que no ;).
Avatar de Usuario
Ximorro
Profesional del Autoit
Mensajes: 1500
Registrado: 10 Jul 2009, 12:35
Ubicación: Castellón, España

Re: Return Multiple

Mensaje por Ximorro »

Hombre, vectores independientes... si son 3 ó 4 los metes en variables con nombre, pero si son unos cuantos o el número va variando sí puede ser interesante agruparlos en un vector.
Pero es cierto que no es del todo cómodo, tienes que sacar el vector antes de acceder a algún elemento suyo, ya podían haber dejado concatenar el acceso a matrices, tipo

Código: Seleccionar todo

$valor = ($a[1])[1]
Ya que $a[1] devuelve un vector, debería poder añadírsele un acceso a vector, pero no, cosas del diseño del lenguaje.

¿Con estructuras de datos te refieres a tipo registros, como los struct de C? Pues efectivamente, como AutoIT no es tipado puedes meter en cualquier variable valores de cualquier tipo, así que tal como dices puedes meter en un vector cadenas, números, booleanos, otros vectores... ¡todo mezclado!

Se pueden hacer fichas bastante complejas, en ejemplo tonto:

Código: Seleccionar todo

Global CONST $noHijos=0 ;No sé cómo hacer un array vacío, así que me apaño con esto...
Global $juan, $ana, $pedro

$juan = _CreaPersona("Juan", 10, $noHijos)
$ana = _CreaPersona("Ana", 3, $noHijos)
Global $hijos[2] = [$juan, $ana]
$pedro = _CreaPersona("Pedro", 42, $hijos)

MsgBox(0, "INFO", _Nombre($pedro) & " tiene " & _NumHijos($pedro) & " hijos." & @CRLF & _
			"Su hija pequeña se llama " & _Nombre(_Hijo($pedro, 2)) & " y tiene " & _Edad(_Hijo($pedro, 2)) & " años.")


Func _CreaPersona($nombre, $edad, $hijos)
	Local $res[3] = [$nombre, $edad, $hijos]
	Return $res
EndFunc

Func _Nombre($persona)
	Return $persona[0]
EndFunc

Func _Edad($persona)
	Return $persona[1]
EndFunc

Func _ListaHijos($persona)
	Return $persona[2]
EndFunc

Func _Hijo($persona, $num)
	Local $h = $persona[2] ;Habría que comprobar rangos
	Return $h[$num-1]
EndFunc

Func _NumHijos($persona)
	Return UBound($persona[2]) ;Con $noHijos UBound dará cero
EndFunc
¿Cómo crear arrays vacíos? Tipo
Global $a[0] = []
Por lo visto debe tener como mínimo un elemento, sería muy cómodo para arrays variables, con UBound sabes cuántos elementos hay, pero no se puede dejar a cero, al menos UBound en una variable no array da 0, pero también activa @error, cosa que ignoro ;-)

Para ser la única estructura que da el lenguaje las matrices no están acabadas, no puedes por ejemplo usarlas directamente y hacer algo como:

Código: Seleccionar todo

$pedro = _CreaPersona("Pedro", 42, [$juan, $ana])
tienes que pasar los hijos por una variable...

Estoy pensando que nos estamos saliendo del tema... ¿que no pondremos esto de las "estructuras" en otro post dedicado para ello? si alguien busca algo sobre estructuras/registros esto puede ayudar, y el post de "retornos múltiples" no es donde debería buscarse algo así...
"¿Y no será que en este mundo hay cada vez más gente y menos personas?". Mafalda (Quino)
Responder