[Guía] Bucles(for,while, etc) mas rápidos(y_iterate)

Aprende lo que no sabes de este lenguaje y encuentra herramientas y códigos útiles.

Moderador: Ayudantes

Reglas del Foro
  • Si tu código es corto, no crees un tema nuevo para liberarlo, publica un mensaje en el tema [Funciones] ¡Publica tu código aquí!.
  • Si creas una guía, debes explicar el código claramente. Evita poner la explicación en forma de comentarios dentro del mismo y no olvides utilizar el BBCode correspondiente: [Pawn]Código aquí[/Pawn].
  • No postear códigos sin probar. Publicar códigos con errores (que impidan compilar el script para el cual está destinado) en este apartado es motivo de sanción.
  • Si tu código necesita plugins, includes u otros códigos adicionales para funcionar, debes mencionarlo en el mensaje.
  • Si has utilizado códigos de otros autores, recuerda colocar los créditos correspondientes. (El plagio es motivo de sanción).
  • Si tu aporte es para un GameMode en específico, debes publicar el tema en el apartado "Guías y Aportes para GameModes específicos".
Responder
Avatar de Usuario
MattHudson
Moderador Global
Moderador Global
Mensajes: 1666
Registrado: 31 Oct 2015 18:16
Ubicación: Argentina, Buenos Aires, San Miguel.
Contactar:
Reputación: 89

22 Sep 2018 20:30

Hola, -hi

Include: y_iterate (mayoritariamente conocido como "foreach", parte de las librerías que nos brinda el "proyecto" YSI, iniciado por Y_Less, ahora mantenido por "Pawn-Lang")
Esta librería proporciona un bucle eficiente a través de conjuntos de datos dispersos, entre ellos, los usuarios conectados, vehículos creados, y los que nosotros queramos crear. Fue mejorado significativamente de la versión original(foreach) para ser un sistema de bucles totalmente genérico, en lugar de un simple sistema de bucles para jugadores conectados a un servidor. Cuando se usa para los jugadores esto tiene un numero exacto a usar en el bucle, dicho numero pertenece al id del usuario conectado(estos números son almacenados para usar ÚNICAMENTE esos números/ids de los usuarios conectados, y no el resto de números/ids que están de sobra/vacíos)... incluso cuando la cantidad de jugadores iguala a la cantidad de MAX_PLAYERS, este método de realizar bucles sigue siendo mas rápido.


¿Como hacer un bucle con y_iterate?:
Si bien la mayoría ya conocemos la sintaxis de "foreach", y_iterate tiene una distinta(en un simbolo y orden únicamente -laughing )
Para jugadores:
 Codigo Pawno:
1
2
3
4

foreach(new JugadoresDelBucle : Player)
{
    SendClientMessage(playerid, -1, "Eres uno de los jugadores conectados(de los que entraron en el bucle).");
}
  Cantidad de llaves: Abiertas(1)-Cerradas(1) | Lineas Totales: 4
Para vehículos:
 Codigo Pawno:
1
2
3
4

foreach(new VehiculosDelBucle : Vehicle)
{
    DestroyVehicle(VehiculosDelBucle); //Esto destruiría todos los vehículos que estén creados(osea, todos los que están en el bucle)
}
  Cantidad de llaves: Abiertas(1)-Cerradas(1) | Lineas Totales: 4
Personalizados:
Simples:
 Codigo Pawno:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

#define MAX_CASAS 800 //Esto lo hacen muchos, por lo tanto lo pongo para no confundir demasiado.
new Iterator:Casas<MAX_CASAS>//Creamos el iterator, le damos un nombre y un numero máximo(en este caso, el valor de MAX_CASAS(osea, 800)).

CargarCasas()//Por lo general se usa esta estructura, por lo tanto lo pongo así para no confundir demasiado.
{
    //Cargan los datos de las cosas, coordenadas, etc etc...
    CrearCasa(CasaID);//Por lo general se usa esta estructura, por lo tanto lo pongo así para no confundir demasiado.
}

CrearCasa(CasaID)
{
    //Crean los pickups/pavadas así y blablablabla...
    Iter_Add(Casas, CasaID);//Y con esto, ya añadimos la casa que creamos(numero de "CasaID", osea, como usamos CrearCasa en "CargarCasas", van a ser todas las casas que se cargaron de donde hayamos guardado los datos y esas cosas...)
}

// Listo. Ahora toca usarlo, que no es nada mas, ni nada menos que:
foreach (new Casa : Casas) //Esto es útil en muchos lados, como el "guardado" de estas cosas, la modificación de variables en muchas a la vez, y alguna que otra cosa. Incluso abre la posibilidad de usar loops en vez de un código repetido, ya que al consumir lo justo y necesario, no hace lo negativo que tiene un loop en esos casos.
{
    SendClientMessageFormatted(playerid, -1, "La casa %d esta creada(paso por CrearCasa).");//(pongo esta función que NO ES NATIVA(no existe) para simular el mensaje nomas). Este mensaje se enviara las veces necesarias a la vez que se valla moviendo el bucle de "Casas". Es decir, si cargamos las casas con id "1,9,15 y 29", se enviaran los mensajes "La casa 1 esta creada(paso por CrearCasa).", "La casa 9 esta creada(paso por CrearCasa).", "La casa 15 esta creada(paso por CrearCasa)." y "La casa 29 esta creada(paso por CrearCasa).".
}
  Cantidad de llaves: Abiertas(3)-Cerradas(3) | Lineas Totales: 20
Multi-dimensionales:
 Codigo Pawno:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

#define CantidadDeNumeros 10
new Iterator:NumerosDeLaLoteriaPorJugador[MAX_PLAYERS]<CantidadDeNumeros >; //Suponiendo que en la lotería cada uno tiene sus resultados diferentes :P
Iter_Init(NumerosDeLaLoteriaPorJugador); //Necesario en los multi-dimensionales, lo explicare mas abajo.

public OnPlayerConnect(playerid);
{
    Iter_Add(NumerosDeLaLoteriaPorJugador[playerid], random(99));
    Iter_Add(NumerosDeLaLoteriaPorJugador[playerid], random(999));
    Iter_Add(NumerosDeLaLoteriaPorJugador[playerid], random(9999));
}

CMD:resultadoloteria(playerid)
{
    foreach(new Resultado : NumerosDeLaLoteriaPorJugador[playerid])
    {
        SendClientMessageFormatted(playerid, -1, "Tu resultado de la lotería es %d.", Resultado);//Se enviara  3 veces y con los números que salieron en el Iter_Add del inicio.
    }
    return 1;
}
// No se me ocurrió ningún otro ejemplo, si bien es irreal, al menos creo que se entiende.
  Cantidad de llaves: Abiertas(3)-Cerradas(3) | Lineas Totales: 20

Funciones:

Iter_Add(Iterator, valor);
- Como ya vimos en los ejemplos, añadimos un numero(en el parametro VALOR) al iterator.

Iter_Remove(Iterator, valor);
-Como iter_add, pero al revés. El otro añade, este remueve. Es decir, si en algún lado del código ponemos un 6 a un iterator con Iter_Add... si usamos Iter_Remove en ese mismo iterator y con el numero 6, sera removido del iterator.

Iter_Contains(Iterator, valor);
- Revisa si el numero puesto en "valor" esta en el iterator especificado en Iterator. Es decir, suponiendo que hablamos del iterator de los jugadores(player), buscamos con esta función el numero 50. Retornara 1 si el numero 50 esta(en este caso, si el numero 50 esta conectado)

Iter_Free(Iterator);
- Obtiene el primer valor que no existe en un iterator. Ejemplo en el iterator de los jugadores(Player): Si ponemos iter_Free con el Player, y el jugador 10 no esta conectado, la función retomara 10. Porque es el primer "slot" del iterator que esta desocupado. Retoma -1 si no hay slots vacíos.

Iter_Count(Iterator);
- Obtiene el numero de valores/números únicos en el iterator. Ejemplo en un iterator que contenga "9,10,11,10,10,9", la función retomara 3. Porque solo el 9, el 10, y el 11 son números únicos, si contara la cantidad en total, retomaría 6.

Iter_Clear(Iterator);
- Vacia el iterator. Como si nunca hubiéramos usado Iter_Add para añadirle valores.

Iter_Random(Iterator);
- Elije un numero al azar de los slots del iterator seleccionado.

Iter_Init(Iterator);
- Los iterators comunes se inician solos debido al uso simple de una sola dimensión, pero los multi-dimensionales(como se vio en el ejemplo de arriba) no... por lo tanto deben ser iniciados con "Iter_Init".

Iter_SafeRemove(Iterator, value, next);
-No puedes usar Iter_Remove adentro de otros loops(osea, adentro de un código foreach) porque, basicamente, crashea y explota todo por los aires. Por lo tanto, esta función evita todos los problemas(a su vez, es relativamente mas lenta porque tiene mayor procedimiento)

Iter_Begin(Iterator);
- Obtiene el primer slot vacio que se ubica antes del primero que si tiene valor.

Iter_End(Iterator);
- El primer slot vacio que viene despues del primer slot que si tiene valor.

Iter_Next(Iterator, cur);
- Obtiene el siguiente valor del iterator. Va a devolver "Iter_End" cuando se llame en ultimo slot con un valor.

Iter_Prev(Iterator, cur);
- Al revés que el de arriba.

Iter_First(Iterator);
- Retoma el primer slot con un valor del iterator. Seria el valor siguiente que retoma Iter_Begin

Iter_Last(Iterator);
- Retoma el ultimo slot con un valor del iterator. Seria el valor siguiente a Iter_End.

Iter_Size(Iterator);
- Devuelve el valor del tamaño del iterator. Ejemplo: en "new Iterator:iIterator<500>;" devolvería 500.

Iter_InternalSize(Iterator);
- Devuelve el valor del tamaño del iterator teniendo en cuenta el macro de "Iterator:". Ejemplo: en "new Iterator:iIterator<500>;" devolvería 501.


Hay muchas otras cosas que no voy a incluir en esta guía, porque... básicamente, sigo tratando de entenderlas(se me hace mas fácil entender latín me parece) y no me parece copiar y pegar cosas que no se ni explicar ni tampoco se usar.

Y con esto concluye la guía. Hay muchas funciones que son realmente útiles, como hay otras que por ahí no usen nunca.
Y a lo importante...
¿Porque usar y_iterate?: En clickbait: Menos lag. En español: Mas eficiencia y menos consumo de memoria en unos loops donde sobran repeticiones de código.

Ah, y su descarga viene con YSI, en la carpeta "YSI_Data".
Última edición por MattHudson el 22 Sep 2018 20:33, editado 1 vez en total.
Razón: Al final lo pondré en guías.
BonerMap
Aprendiz
Aprendiz
Mensajes: 330
Registrado: 01 Dic 2014 09:34
Ubicación: México
Contactar:
Reputación: 9

22 Sep 2018 22:49

Muy buena guía,gracias por compartirla.

Saludos -hi
//_____________________MIS PROYECTO_____________________________//
GO PLAYERS ROLEPLAY
______________________________________________________
_____________________APORTES A EL FORO_________________
Spoiler:
[Mapeo 24/7]:http://pawnscript.com/foro/viewtopic.php?t=3882
[APORTE[Sistema loro FZ]:http://pawnscript.com/foro/viewtopic.php?t=23531
[FS][Fiesta de la cerveza]:http://pawnscript.com/foro/viewtopic.php?f=81&t=28704
[APORTE]Localizar propiedad OZ:http://pawnscript.com/foro/viewtopic.php?f=40&t=28872
[APORTE] FC Para OZ:http://pawnscript.com/foro/viewtopic.php?f=40&t=28892
[APORTE Cambiar contraseña GM OZ]: http://pawnscript.com/foro/viewtopic.php?f=90&t=31309
[APORTE Cambiar nombre en el juego OZ]: http://pawnscript.com/foro/viewtopic.php?f=90&t=31308
//___________________________________________________________________________
Yo no soy programador.
Me gusta ayudar a la gente.
**************Prónto Médico********************************
Pwn: Mi pasatiempo :)
Avatar de Usuario
dello
Ayudante
Ayudante
Mensajes: 257
Registrado: 09 Jun 2014 19:08
Contactar:
Reputación: 5

23 Sep 2018 01:55

Muy bonita -good
Licenciatura en Cs de la computación

tostad0r - Toaster - Dello


Avatar de Usuario
MattHudson
Moderador Global
Moderador Global
Mensajes: 1666
Registrado: 31 Oct 2015 18:16
Ubicación: Argentina, Buenos Aires, San Miguel.
Contactar:
Reputación: 89

23 Sep 2018 16:51

dello escribió:
23 Sep 2018 01:55
Muy bonita -good
Gracias -good

De todas formas nada de eso seria posible de no ser por la documentación del include en sí.
Responder