15 agosto 2007

El objeto StringList (II)

Vamos a seguir viendo las características de la clase TStringList.

ELIMINANDO ELEMENTOS DE LA LISTA

Con el método Delete se elimina un elementos de la lista la cual vuelve a reagrupar sus elemento asignando un nuevo índice. Actualmente la lista de clientes contiene:

CARLOS ABENZA MARTINEZ
PASCUAL CAMPOY FERNANDEZ
MARIA PALAZÓN PÉREZ
PEDRO SANCHEZ GARCIA
ROSA GUILLÉN LUNA
LUIS GARCIA ROJO
MANUEL ESCUDERO BERNAL

Vamos a eliminar a ROSA de la lista:

Clientes.Delete( 4 );

Ahora el cliente LUIS tiene un índice de 4 (en vez de 5 como antes), es decir, al contrario de un array dinámico, si en un objeto StringList se elimina un elemento de la lista no queda ningún hueco, ya que vuelven a agruparse sus elementos.

Un error común para eliminar todos los elementos de la lista sería hacer lo siguiente:

var
i: Integer;
begin
for i := 0 to Clientes.Count - 1 do
Clientes.Delete( i );
end;

Nos daría el error:

List index out of bounds(3)

¿Por qué ocurre esto? Pues por la sencilla razón de que cada que se elimina un elemento, al reagruparse el resto de los elementos se va también disminuyendo el número de los mismos y sus índices, con lo cual cuando intenta acceder a un elemento que ya no existe provoca un error. La manera correcta de hacerlo sería:

var
i: Integer;
begin
for i := 0 to Clientes.Count - 1 do
Clientes.Delete( 0 );
end;

Como vemos arriba se elimina sólo el primer elemento y como se van eliminando como si fuera una pila de platos al final desaparecen todos. Naturalmente una clase StringList dispone del método Clear que elimina todos los elementos de la lista:

Clientes.Clear;

MOVIENDO ELEMENTOS EN LA LISTA

Supongamos que tenemos la anterior lista de clientes:

CARLOS ABENZA MARTINEZ
PASCUAL CAMPOY FERNANDEZ
MARIA PALAZÓN PÉREZ
PEDRO SANCHEZ GARCIA
LUIS GARCIA ROJO
MANUEL ESCUDERO BERNAL

Vamos a mover a MARIA a la primera posición de la lista:

Clientes.Move( 2, 0 );

El comando Move acepta como primer parámetro en que posición esta el elemento que deseamos mover y como segundo parámetro su destino. En el caso anterior llevamos a MARIA de la posición 2 a la 0:

MARIA PALAZÓN PÉREZ
CARLOS ABENZA MARTINEZ
PASCUAL CAMPOY FERNANDEZ
PEDRO SANCHEZ GARCIA
LUIS GARCIA ROJO
MANUEL ESCUDERO BERNAL

Ahora bien, no hay que confundirse el mover elementos en la lista con intercambiarlos. El mover un elemento sólo lo elimina de la posición actual y lo lleva a la posición deseada, pero mantiene el orden natural de la lista. Si lo que queremos es intercambiar dos elementos para ello disponemos del método Exchange el cual tiene los mismos parámetros que Move salvo que lo que hace es intercambiar las posiciones de ambos elementos.

Vamos a ver como cambiar la posición de MANUEL (que es la 5) con la de CARLOS (que es la 1):

Clientes.Exchange( 5, 1 );

Su resultado sería:

MARIA PALAZÓN PÉREZ
MANUEL ESCUDERO BERNAL
PASCUAL CAMPOY FERNANDEZ
PEDRO SANCHEZ GARCIA
LUIS GARCIA ROJO
CARLOS ABENZA MARTINEZ


BUSCANDO ELEMENTOS EN LA LISTA

Se puede averiguar la posición de un elemento en la lista con con los métodos IndexOf e IndexOfName:

function IndexOf( const S: string ): Integer; override;
function IndexOfName(const Name: string): Integer; virtual;


El método IndexOf toma como parámetro el nombre del elemento que se desea buscar y devuelve su índice si lo encuentra (el primer elemento es el cero) y -1 si no lo encuentra. Por ejemplo:

Clientes.IndexOf( 'PEDRO SANCHEZ GARCIA' ) devuelve 3
Clientes.IndexOf( 'PEDRO SANCHEZ' ) devuelve -1

La función IndexOf sólo busca el primer elemento encontrado en la lista, de modo que si hay dos elementos iguales sólo muestra el índice del primero (de ahí la importancia de tener la lista ordenada).

Después tenemos la función IndexOfName destinada a buscar elementos de tipo NOMBRE = VALOR como vimos anteriormente con el diccionario:

Diccionario.IndexOfName( 'BOOK' ) devuelve 0
Diccionario.IndexOfName( 'MOUSE' ) devuelve 1
Diccionario.IndexOfName( 'TABLE' ) devuelve 2

Por último tenemos la función Find utilizada para buscar elementos sólo si la lista esta ordenada. Por ejemplo:

var
iPosicion: Integer;
bEncontrado: Boolean;
begin
Clientes.Sort; // ordenamos la lista
bEncontrado := Clientes.Find( 'PEDRO SANCHEZ GARCIA', iPosicion );
end;

La función Find es similar a función IndexOf añadiendo como segundo parámetro una variable donde depositar la posición del elemento buscado y cuyo valor devuelto en la función será True o False dependiendo si ha encontrado el elemento en la lista.

Después de ejecutar este código la lista quedaría de la siguiente manera:

CARLOS ABENZA MARTINEZ
LUIS GARCIA ROJO
MANUEL ESCUDERO BERNAL
MARIA PALAZÓN PÉREZ
PASCUAL CAMPOY FERNANDEZ
PEDRO SANCHEZ GARCIA

La variable bEncontrado valdría True y iPosicion sería igual a 5.

En el próximo artículo terminaremos de ver todas las funcionalidades de un StringList.

Pruebas realizadas en Delphi 7.

No hay comentarios:

Publicidad