BotonMenu
BotonIndice

Visita : conoce3000.com
Paypal : https://www.paypal.com/donate/?hosted_button_id=XY8TZ3MGN64GE

PASCAL CON FREE PASCAL

PASCAL CON FREE PASCAL

PASCAL CON FREE PASCAL


13. LISTAS Y COLECCIONES.
13.2. CREANDO Y MANEJANDO LISTAS.
13. LISTAS Y COLECCIONES.
13.2. CREANDO Y MANEJANDO LISTAS.
13. LISTAS Y COLECCIONES.
13.2. CREANDO Y MANEJANDO LISTAS.

SIGUIENTE

SIGUIENTE

SIGUIENTE


‒ Creando y manejando listas.

Las listas tanto TList como TFPList, tienen los métodos y propiedades necesarios para su manipulación como son añadir, insertar, borrar elementos de una lista y otros más. TList y TFPList son clases que permiten en realidad manejar o manipular un arreglo de punteros. En la siguiente tabla se explica brevemente algunos de ellos.


Método Descripción
Add Permite añadir un puntero a la lista.
Insert(i) Permite insertar un puntero a la lista, en la posición indicada por i
Delete Pone a Nil un puntero de la lista.
Exchange(i,j) Permite intercambiar dos punteros de la lista indicados por i y j.
Move(i,j) Permite mover un puntero de la posición i a la posición indicada por j, en la lista.
First Permite obtener el primer puntero diferente a nil de la lista.
Last Permite obtener el último puntero diferente a nil de la lista.
Clear Borra sólo la lista de punteros, pero no las variables dinámicas o objetos a los que apuntan cada puntero de la lista.
Pack Permite liberar espacio ocupado por los punteros de la lista que tengan nil.
Items[i] Es una atributo que nos permite acceder a un puntero de la lista indicado por el indice i. La listas se enumeran empezando con 0. Es decir el primer elemento de la lista es Items[0].
Capacity Es un atributo que nos indica la cantidad de punteros que puede usar la lista.
Count Es un atributo que nos indica la cantidad de punteros que tiene la lista.

Debido a que TList y TFPList manejan un arreglo de punteros cada vez que queremos acceder a uno de los elementos de la lista, se debe hacer un solapamiento con el tipo de dato correspondiente. Además se debe tener presente que antes de borrar una lista o destruir una lista, se debe borrar todas las variables dinámicas a las que apuntan los punteros de la lista, ya que si no estos se quedarán ocupando espacio mientras duré la ejecución del programa. Ejemplo:


Descargar
{$codepage utf8}
{$mode objfpc}
Uses sysutils,classes;
Var ListaN,ListaD:Tlist;
    n:^integer;
    d:^double;
    i:byte;
Begin
  randomize;
  ListaN:=Tlist.create;
  ListaD:=Tlist.create;
  for i:=0 to 10 do
    begin
      new(n);new(d);
      n^:=random(1000);
      d^:=random;
      ListaN.add(n);
      ListaD.add(d);
    end;

  Writeln('ListaN');
  Writeln('Capacidad = ',ListaN.Capacity);
  Writeln('Cantidad = ',ListaN.Count);

  for i:=0 to 10 do Writeln('[',i:2,'] ',integer(ListaN.items[i]^));

  Writeln('Borrando');
  //Si no usamos freemem para eliminar las variables dinámicas
  //n estaría apuntando a la última variable dinámica creada.
  for i:=0 to 10 do freemem(ListaN.items[i]);

  //Pone la lista a nil y la cantidad a 0
  ListaN.clear;
  ListaN.destroy;

  Writeln('ListaD');
  Writeln('Capacidad = ',ListaD.Capacity);
  Writeln('Cantidad = ',ListaD.Count);
  for i:=0 to 10 do Writeln('[',i:2,'] ',double(ListaD.items[i]^):0:3);

  Writeln('Borrando');
  //Si no usamos freemem para eliminar las variables dinámicas
  //d estaría apuntando a la última variable dinámica creada.
  for i:=0 to 10 do freemem(ListaD.items[i]);

  //Pone la lista a nil y la cantidad a 0
  ListaD.clear;
  ListaD.destroy;

End.
Código fuente 1: Creando y manejando un lista.
Descargar

En el ejemplo anterior se crean dos listas una de números enteros y la otro de números reales, para eliminar las variables dinámicas se hace uso de freemem y no de dispose, esto es debido a que los elementos de la lista son punteros sin tipo, es decir son del tipo pointer.

Si deseamos hacer una lista de cadena de caracteres del tipo ansistring o unicodestring, debemos hacer un artificio, ya que estos tipos de datos a pesar de ser variables dinámicas se comportan como variables estáticas de tipo string. El artificio consiste en crear un puntero a un registro que contenga una cadena de caracteres como uno de sus campos. Y el puntero a registro es el que se va colocando a la lista. Ejemplo:


Descargar
{$codepage utf8}
{$mode objfpc}
Uses sysutils,classes;
Type TCad=Record
            cad:unicodestring
          End;
Var Lista:Tlist;
    i:byte;
    Pcad:^TCad;
Begin
  randomize;
  Lista:=Tlist.create;
  for i:=0 to 10 do
    begin
      new(Pcad);
      Pcad^.cad:='Numero '+IntToStr(random(1000));
      Lista.add(Pcad);
    end;
  for i:=0 to 10 do writeln(TCad(Lista.items[i]^).cad);

  Writeln('Capacidad = ',Lista.Capacity);
  Writeln('Cantidad = ',Lista.Count);
  Writeln('Borrando');

  for i:=0 to 10 do freemem(Lista.items[i]);

  Lista.clear;
  Lista.destroy

End.
Código fuente 2: Lista con cadena de caracteres.
Descargar

Debido a que una instancia o objeto de una clase en realidad es un puntero a una estructura que representa una clase, estos también se pueden usar con listas, pero al momento de usar una elemento de la lista debemos hacer el solapamiento con el tipo de dato de la clase. Ejemplo:


Descargar
{$codepage utf8}
{$mode objfpc}
Uses sysutils,classes;

Type
   TPersona=class
     Nombre,Ciudad:string;
     Procedure MostrarPersona;
   End;

   Procedure TPersona.MostrarPersona;
    Begin
      Writeln('Nombre:',Nombre);
      Writeln('Ciudad:',Ciudad)
    End;

Var Lista:Tlist;
    rpta:char;
    i:byte;
    Persona:TPersona;
    aux:pointer;
Begin
  Lista:=Tlist.create;

  Repeat
    Persona:=TPersona.create;
    Write('Nombre : ');Readln(Persona.Nombre);
    Write('Ciudad : ');Readln(Persona.Ciudad);
    Lista.add(Persona);
    Write('Desea continuar [S]i [N]o : ');readln(rpta)
  Until (rpta='N') or (rpta='n');

  for i:=0 to lista.Count-1 do TPersona(Lista.items[i]).MostrarPersona;

  Writeln('Capacidad = ',Lista.Capacity);
  Writeln('Cantidad = ',Lista.Count);
  Writeln('Borrando');

  //Si no usamos destroy para eliminar las instancias
  //estas estarán ocupando memoria RAM en la computadora.

  for i:=0 to lista.Count-1  do TPersona(Lista.items[i]).destroy;

  Lista.clear;
  Lista.destroy
End.
Código fuente 3: Lista con objetos.
Descargar

Tal como se puede observar del ejemplo anterior, no se puede usar freemem para borrar las instancias o los objetos colocados en la lista, se debe usar el destructor correspondiente del objeto, que en este caso es destroy. En cualquier caso cuando se manejan listas y se deben eliminar algún elemento de la lista se debe eliminar antes la variable dinámica u objeto al que apunta el puntero de la lista.

El siguiente ejemplo muestra el uso de los métodos insert, delete, exchange, move, first, last y pack.


Descargar
{$codepage utf8}
{$mode objfpc}
Uses sysutils,classes;

Type
   TCadenas=class
     Cad:ansistring;
     Constructor crear(ccad:ansistring);
   End;

   Constructor TCadenas.crear(ccad:ansistring);
     Begin
       cad:=ccad
     End;

Var Lista:Tlist;
    i:byte;

Begin
  Lista:=Tlist.create;
  for i:=0 to 10 do Lista.add(TCadenas.crear('Numero '+intTostr(i)));

  for i:=0 to lista.Count-1 do Writeln('[',i:2,']',TCadenas(Lista.items[i]).cad);

  Writeln('======== INSERTANDO EN 5 ========');
  //inserta el elemento en la posición 5, el que se encuentra en esa
  //posición se desplaza a la siguiente

  Lista.Insert(5,TCadenas.Crear('insertado'));

  Writeln('Capacidad = ',Lista.Capacity);
  Writeln('Cantidad = ',Lista.Count);

  for i:=0 to lista.Count-1 do Writeln('[',i:2,']',TCadenas(Lista.items[i]).cad);

  Writeln('======== BORRANDO 5 ========');
  //Se debe destruir antes de borrar el elemento de la lista
  //Borra el elemento en la posición 5, pone el puntero a nil,
  //no borra a lo que apunta el puntero o la instancia de una clase.

  TCadenas(Lista.items[5]).destroy;
  Lista.Delete(5);

  Writeln('Capacidad = ',Lista.Capacity);
  Writeln('Cantidad = ',Lista.Count);

  for i:=0 to lista.Count-1 do Writeln('[',i:2,']',TCadenas(Lista.items[i]).cad);

  Writeln('======== INTERCAMBIANDO 1 con 4 ========');
  Lista.Exchange(1,4);
  for i:=0 to lista.Count-1 do Writeln('[',i:2,']',TCadenas(Lista.items[i]).cad);

  Writeln('======== MOVIENDO 4 a 1 ========');
  Lista.Move(4,1);
  for i:=0 to lista.Count-1 do Writeln('[',i:2,']',TCadenas(Lista.items[i]).cad);

  Writeln('======== MOVIENDO 2 a 4 ========');
  Lista.Move(2,4);
  for i:=0 to lista.Count-1 do Writeln('[',i:2,']',TCadenas(Lista.items[i]).cad);

  Writeln('El primero elemento de la lista es : ',TCadenas(Lista.First).cad);
  Writeln('El ultimo elemento de la lista es : ',TCadenas(Lista.Last).cad);

  Lista.pack;
  Lista.destroy
End.
Código fuente 4: Uso de insert, delete, exchange, move, first, last y pack.
Descargar

En este ejemplo para añadir los elementos a la lista se hace uso de una clase que contiene un constructor, que nos permite colocar un contenido a la cadena de caracteres que la clase contiene. Cuando insertamos un puntero u objeto a la lista en la posición indica los elementos a partir de la posición se desplazan todos a la siguiente, y como se puede observar al eliminar un elemento de la lista debemos de eliminar la variable dinámica o objeto al que apunta el puntero, ya que cuando se usa el método delete, lo que se hace es poner a nil el puntero.

Otros métodos que tienen Tlist y TFPList son Extract, Remove y IndexOf, estos necesitan como parámetro un puntero, la siguiente tabla describe su funcionamiento.


Método Descripción
Extrac(p) Coloca a nil el primer puntero p, que encuentre en la lista y devuelve el puntero encontrado para su posterior uso.
Remove(p) Coloca a nil el primer puntero p, que encuentre en la lista y devuelve la posición en donde fue encontrado, en caso no lo encontró devuelve un -1.
IndexOf(p) Busca el primer puntero p, que encuentre en la lista y devuelve la posición en donde fue encontrado, en caso no lo encontró devuelve un -1.

Aunque obviamente no es muy natural para el ser humano buscar punteros en una lista, estos métodos se suelen usar para buscar objetos en la lista, y se suele usar cuando hay varias listas y se desea saber si un objeto se encuentra en una lista o en la otra. Por ejemplo el método extract devuelve el objeto encontrado (es decir el puntero), y su uso posterior puede ser colocarlo en otra lista, y en el caso del método Remove, que devuelve la posición en donde encontró el puntero se puede usar simplemente para borrar el objeto de la lista porque este ya se encuentra en otra lista. Ejemplo:


Descargar
{$codepage utf8}
{$mode objfpc}
Uses sysutils,classes;

Type
   TCadenas=class
     Cad:ansistring;
     Constructor crear(ccad:ansistring);
   End;

   Constructor TCadenas.crear(ccad:ansistring);
     Begin
       cad:=ccad
     End;

Var Lista01,Lista02,Lista03:Tlist;
    aux:pointer;
    i:byte;
Begin
   Lista01:=Tlist.create;
   Lista02:=Tlist.create;
   Lista03:=Tlist.create;

   Writeln('=====LISTA01=====');
   Lista01.Add(TCadenas.crear('Juan'));
   Lista01.Add(TCadenas.crear('Jose'));
   Lista01.Add(TCadenas.crear('Miguel'));
   Lista01.Add(TCadenas.crear('Ana'));
   for i:=0 to lista01.Count-1 do Writeln('[',i:2,']',TCadenas(Lista01.items[i]).cad);


   Writeln('=====LISTA02=====');
   Lista02.Add(Lista01.items[2]); //Miguel
   Lista02.Add(TCadenas.crear('Sofia'));
   Lista02.Add(TCadenas.crear('Mary'));
   Lista02.Add(Lista01.items[0]); //Juan
   for i:=0 to lista02.Count-1 do Writeln('[',i:2,']',TCadenas(Lista02.items[i]).cad);

   Writeln('=====LISTA03=====');
   Lista03.Add(Lista02.items[2]); //Mary
   Lista03.Add(TCadenas.crear('Grace'));
   Lista03.Add(TCadenas.crear('Luis'));
   Lista03.Add(Lista01.items[0]); //Juan
   for i:=0 to lista03.Count-1 do Writeln('[',i:2,']',TCadenas(Lista03.items[i]).cad);

   Writeln('Buscando a Juan en la lista 02 y lista 03');
   aux:=Lista01.items[0];
   if Lista02.indexof(aux)>=0 then
      Writeln('Esta en la lista 02')
   else writeln('no se encontro en lista02');
   if Lista03.indexof(aux)>=0 then
      Writeln('Esta en la lista 03')
   else writeln('no se encontro en lista03');

   Writeln('Buscando a Grace en la lista 01 y lista 02');
   aux:=Lista03.items[1];
   if Lista01.indexof(aux)>=0 then
      Writeln('Esta en la lista 01')
   else writeln('no se encontro en lista01');
   if Lista02.indexof(aux)>=0 then
      Writeln('Esta en la lista 02')
   else writeln('no se encontro en lista02');

   Writeln('Borrando a Mary de lista03 para ponerlo en la lista 01');
   aux:=Lista03.Extract(Lista02.items[2]);
   Lista01.add(aux);

   Writeln('=====LISTA03=====');
   for i:=0 to lista03.Count-1 do
     Writeln('[',i:2,']',TCadenas(Lista03.items[i]).cad);
   Writeln('=====LISTA01=====');
   for i:=0 to lista01.Count-1 do
     Writeln('[',i:2,']',TCadenas(Lista01.items[i]).cad);

   Writeln('Borrando a Juan de la lista03, pero dejandolo en lista01');

   Lista03.remove(Lista01.items[0]);
   Writeln('=====LISTA03=====');
   for i:=0 to lista03.Count-1 do
     Writeln('[',i:2,']',TCadenas(Lista03.items[i]).cad);
   Writeln('=====LISTA01=====');
   for i:=0 to lista01.Count-1 do
     Writeln('[',i:2,']',TCadenas(Lista01.items[i]).cad);

End.
Código fuente 5: Uso de extract, remove y indexof.
Descargar

Otro método que es muy útil en las listas y bastante fácil de entender es el método Addlist, lo que hace este método es añadir todos los punteros de otra lista en la lista del método que lo contienen. Ejemplo:


Descargar
{$codepage utf8}
{$mode objfpc}
Uses sysutils,classes;

Type
   TCadenas=class
     Cad:ansistring;
     Constructor crear(ccad:ansistring);
   End;

   Constructor TCadenas.crear(ccad:ansistring);
     Begin
       cad:=ccad
     End;

Var Lista01,lista02,lista03:Tlist;
    i:byte;
Begin
  Lista01:=Tlist.create;
  for i:=0 to 10 do Lista01.add(TCadenas.crear('Numero '+intTostr(i)));

  Lista02:=Tlist.create;
  for i:=11 to 20 do Lista02.add(TCadenas.crear('Numero '+intTostr(i)));

  Lista03:=Tlist.create;
  Lista03.AddList(Lista01);
  Lista03.AddList(Lista02);

  for i:=0 to lista03.Count-1 do Writeln(TCadenas(Lista03.items[i]).cad);
End.
Código fuente 6: Uso de Addlist.
Descargar

En los ejemplos anteriores hemos recorrido las listas usando un for desde 0 hasta Count-1, esto se puede abreviar o hacer de un modo más cómodo con el uso de un bucle for in loop.

La clase Tlist y TFPList están diseñadas para trabajar con este bucle, sólo se necesita crear una variable de control de tipo pointer, para recorrer la lista con el bucle for in loop. Es decir algo como esto :

for i:=0 to Lista01.Count-1 do Writeln(Integer(ListaN.items[i]^))

se puede escribir de la siguiente manera:

for aux in ListaN do Writeln(integer(aux^))

En donde aux es una variable de tipo pointer, y si queremos eliminar los elementos de una lista también se puede hacer del siguiente modo:

for aux in ListaN do freemem(aux)

A continuación el código fuente 01, visto anteriormente con el uso de for in loop.


Descargar
{$codepage utf8}
{$mode objfpc}
Uses sysutils,classes;
Var ListaN,ListaD:Tlist;
    n:^integer;
    d:^double;
    i:byte;
    aux:pointer;
Begin
  randomize;
  ListaN:=Tlist.create;
  ListaD:=Tlist.create;
  for i:=0 to 10 do
    begin
      new(n);new(d);
      n^:=random(1000);
      d^:=random;
      ListaN.add(n);
      ListaD.add(d);
    end;

  Writeln('ListaN');
  Writeln('Capacidad = ',ListaN.Capacity);
  Writeln('Cantidad = ',ListaN.Count);

  i:=0;
  for aux in ListaN do
    Begin
      Writeln('[',i:2,'] ',integer(aux^));
      i+=1
    End;

  Writeln('Borrando');

  for aux in ListaN do freemem(aux);

  ListaN.clear;
  ListaN.destroy;

  Writeln('ListaD');
  Writeln('Capacidad = ',ListaD.Capacity);
  Writeln('Cantidad = ',ListaD.Count);

  i:=0;
  for aux in ListaD do
    Begin
      Writeln('[',i:2,'] ',double(aux^):0:3);
      i+=1
    End;

  Writeln('Borrando');

  for aux in ListaD do freemem(aux);

  ListaD.clear;
  ListaD.destroy
End.
Código fuente 7: Uso de for in loop.
Descargar

En caso se usan objetos en vez de punteros como se vio anteriormente podemos usar como variable de control un puntero o un objeto de la clase correspondiente que se usa en la lista. En caso de usar un puntero se debe hacer un solapamiento de la variable de control con la clase correspondiente al objeto. Es decir en el siguiente código:

for aux in lista do TPersona(aux).MostrarPersona;

La variable aux es de tipo pointer, entonces a esta variable se le debe hacer un solapamiento con la clase TPersona, del cual son los objetos que están en la lista.

Por otro lado en caso de usar un objeto como variable de control, entonces se debe hacer un solapamiento de la variable de control con el tipo de dato pointer. Es decir en el siguiente código:

for pointer(Persona) in lista do Persona.MostrarPersona;

Persona es un objeto de la clase TPersona y se hace un solapamiento con pointer para acceder a los elementos de la lista. En el siguiente ejemplo es el mismo ejemplo 04 pero con el uso de for in loop, usando como variable de control al objeto Persona.


Descargar
{$codepage utf8}
{$mode objfpc}
Uses sysutils,classes;

Type
   TPersona=class
     Nombre,Ciudad:string;
     Procedure MostrarPersona;
   End;

   Procedure TPersona.MostrarPersona;
    Begin
      Writeln('Nombre:',Nombre);
      Writeln('Ciudad:',Ciudad)
    End;

Var Lista:Tlist;
    rpta:char;
    Persona:TPersona;
Begin

  Lista:=Tlist.create;

  Repeat
    Persona:=TPersona.create;
    Write('Nombre : ');Readln(Persona.Nombre);
    Write('Ciudad : ');Readln(Persona.Ciudad);
    Lista.add(Persona);
    Write('Desea continuar [S]i [N]o : ');readln(rpta)
  Until (rpta='N') or (rpta='n');

  for pointer(Persona) in lista do Persona.MostrarPersona;

  Writeln('Capacidad = ',Lista.Capacity);
  Writeln('Cantidad = ',Lista.Count);
  Writeln('Borrando');

  for pointer(Persona) in Lista do Persona.destroy;

  Lista.clear;
  Lista.destroy
End.
Código fuente 8: Uso de for in loop con objetos.
Descargar




SIGUIENTE
SIGUIENTE
SIGUIENTE


 
‒ Comentarios y sugerencias.

Agradezco de antemano, todo comentario, sugerencia, y donativo a través de , que ayude a mejorar los contenidos educativos de Conoce 3000. Además, cualquier pregunta o duda que tengas lo puedes hacer por este medio. Pero, todo contenido que pueda resultar ofensivo, malicioso, racista, sexista, discriminatorio, obsceno, vulgar será eliminado. Para clases particulares contactame por whatsapp al 📲 (+51) 999 264 073








PORTADA |  INTERESANTE |  APUNTES |  LIBROS |  GALERIA


Creative Commons License


Todos los textos, imágenes y videos de Conoce3000 estan colocados bajo una licencia : Creative Commons Reconocimiento-NoComercial 3.0 Unported License.