Página 1 de 1

Return Multiple

Publicado: 07 Jun 2010, 00:12
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

Re: Return Multiple

Publicado: 07 Jun 2010, 00:21
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.

Re: Return Multiple

Publicado: 07 Jun 2010, 08:26
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.

Re: Return Multiple

Publicado: 26 Jul 2010, 19:27
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

Re: Return Multiple

Publicado: 27 Jul 2010, 00:06
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.

Re: Return Multiple

Publicado: 27 Jul 2010, 06:05
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

Re: Return Multiple

Publicado: 27 Jul 2010, 09:14
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 ;-)

Re: Return Multiple

Publicado: 27 Jul 2010, 11:37
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.

Re: Return Multiple

Publicado: 28 Jul 2010, 09:32
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í...