Listas y Diccionarios en C#
Cómo crear y utilizar las colecciones de listas y diccionarios.
Ambos funcionan de manera similar a los arreglos o arrays pero con algunas diferencias importantes. Vamos a echarle un vistazo a la clase
List primero.
Una lista es como un arreglo que cambia de tamaño dinámicamente. Esto significa que no necesitas saber cuántos elementos va a tener por adelantado. Antes de entrar en materia vamos a crear una clase rápidamente que podamos ordenar en nuestra
List.
Desde que una lista es genérica puede guardar cualquier tipo. Pero para nuestro ejemplo, vamos a crear una clase llamada
BadGuy. De esta manera, podemos tener una lista de todos los
BadGuy. Esta clase no tendrá herencia, pero sí dos campos públicos llamados
name y
power, y un constructor para asignar estos valores.
public class BadGuy
{
public string name;
public int power;
public BadGuy(string newName, int newPower)
{
name = newName;
power = newPower;
}
}Ahora podemos empezar a hacer nuestra
List (lista). Lo primero que se debe hacer cuando se hace una lista es incluir el
namespace
System.CollectionsGeneric vamos a hacerlo en la parte superior del script.
Luego declaramos
List. Esta es una clase genérica, entonces ponemos el nombre de la clase después de cualquier modificador, seguido por un tipo que querramos guardar en la lista. En nuestro caso,
BadGuy. Luego le damos un nombre a la lista y dado que
List es una clase invocamos un constructor.
using UnityEngine;
using System.Collections.Generic;
public class SomeClass : MonoBehaviour
{
void Start()
{
List<BadGuy> badGuys = new List<BadGuy>();
}
}Actualmente, nuestra lista está vacía; entonces, vamos a asignarle cosas. Para hacerlo usamos la función
Add(). Esto agregará un elemento nuevo al final de la lista. El parámetro para la función
Add() es el objeto que se está agregando a la lista. En nuestro caso, vamos a invocar un constructor para la clase
BadGuy. Ahora, vamos a poblar la lista.
using UnityEngine;
using System.Collections.Generic;
public class SomeClass : MonoBehaviour
{
void Start()
{
List<BadGuy> badGuys = new List<BadGuy>();
badGuys.Add(new BadGuy("Harvey", 50));
badGuys.Add(new BadGuy("MAgneto", 100));
badGuys.Add(new BadGuy("Pip", 5));
}
}Los elementos en una lista pueden accederse de la misma manera que un arreglo o array, usando un índice. También tiene una propiedad
count, la misma que funciona de la misma manera que la propiedad
Length de los arrays (arreglos).
Las listas tienen funciones como
RemoveAt() e
Insert() para organización manual.
RemoveAt()elimina un elemento de la lista en un índice determinado y mueve todos los elementos que están delante suyo un puesto hacia adelante.
badGuys.RemoveAt(0);
Insert() toma un índice y un elemento, empujando cada elemento después de cada índice hacia arriba un puerto.
badGuys.Insert(0, new BadGuy("keiko", 999));Una de las funciones más poderosas de una lista es
Sort(). Esta se puede usar para ordenar una lista de un tipo determinado por cualquier variable de ese tipo. Depende del tipo que implementa la interfaz
IComparable. Regresemos a nuestra clase
BadGuy e implementémosla.
Primero,
IComparable está en el
namespace
System; por lo tanto necesitamos declarar que estamos usándolo. Luego, necesitamos decirle que esta clase está implementando la interfaz. Esto se parece a la herencia. Vamos a usar el genérico
IComparable y su tipo genérico necesita estar en esta clase. Por último, para completar el contrato de la interfaz
IComparable necesitamos declarar una función pública llamada
CompareTo, la misma que regresa un entero y toma nuestro tipo genérico,
BadGuy, como un parámetro.
public interface IComparable
{
void CompareTo(T other);
}
public class BadGuy, IComparable<BadGuy>
{
public string name;
public int power;
public BadGuy(string newName, int newPower)
{
name = newName;
power = newPower;
}
public int CompareTo(BadGuy other)
{
}
}La idea detrás del método
CompareTo es que el objeto del que se invoca es mayor que el objeto que se toma como parámetro, entonces la función regresa un positivo. Si el objeto del que se invoca el método es menor que el objeto que se toma como parámetro, entonces la función regresa un negativo. Y si son iguales, la función regresa un 0.
public int CompareTo(BadGuy other)
{
if(other == null)
{
return 1;
}
return power - other.power;
}Por lo tanto, regresará un positivo si el método
BadGuy del que se invoca es mayor. Ten en cuenta que podríamos haber basado este resultado en cualquier cosa. La interfaz solo requiere que implementemos el método.
Ahora para organizar la lista usando esta comparación, invocamos
badguys.Sort(). Vamos a registrar la lista de
BadGuy a la consola para mostrar que han sido ordenados.
badGuys.Sort();
foreach(BadGuy guy in badGuys)
{
print(guy.name + " " + guy.power);
}Para empezar la lista de nuevo y eliminar todos los elementos usa la función
Clear() (despejar).
badGuys.Clear();Estas no son todas las funciones de la clase
List. Cubrirlo todo está fuera del enfoque de este blog. Para obtener más información, por favor consulta la información relacionada vinculada abajo.
Los diccionarios funcionan de manera similar a las listas, pero tiene dos tipos. Esto significa que cada elemento constituye un
Key Value Pair. (par clave-valor), que también se conoce por sus siglas KVP.
Los diccionarios también se diferencian de las lista en su propósito. Una lista se usa generalmente en vez de un arreglo donde se necesita más flexibilidad o funcionalidad. Un diccionario se usa como una colección de valores que pueden accederse por una o más keys.
El proceso para declarar un
Dictionary es muy similar al que se sigue para declarar una
List. Primero, incluye el espacio de nombre
System.Collections.Generic Luego, declara una variable igual que antes, pero con dos tipos genéricos. El primer tipo es la clave o key Este es el tipo que sirve de referencia para acceder al segundo tipo, el cual es el valor.
using UnityEngine;
using System.Collections.Generic;
public class SomeOtherClass : MonoBehaviour
{
void Start()
{
Dictionary<string, BadGuy> badGuys = new Dictionary<string, BadGuy>();
}
}En nuestro ejemplo, tenemos un tipo string para la clave, y un valor de tipo
BadGuy.
Estamos usando este diccionario para guardar palabras de búsqueda diferentes que puedan usarse para identificar
BadGuys específicos.
En nuestro método
Start(), declaramos dos
BadGuys. Luego los agregamos al Diccionario, al igual que lo hicimos con la lista. Solo que esta vez estamos agregando datos para ambos la key (clave) y el value (valor).
using UnityEngine;
using System.Collections.Generic;
public class SomeOtherClass : MonoBehaviour
{
void Start()
{
Dictionary<string, BadGuy> badGuys = new Dictionary<string, BadGuy>();
BadGuy bgHarvey = new BadGuy("Harvey", 50);
BadGuy bgMagneto = new BadGuy("Magneto", 100);
badGuys.Add("gangster", bgHarvey);
badGuys.Add("mutant", bgMagneto);
}
}Acceder a los valores que se refieran a una clave se realiza de manera similar a acceder a los elementos de un arreglo o una lista. Sin embargo, en vez de usar un índice, que no tiene ningún significado inherente para un diccionario, insertamos una clave dentro de los corchetes.
BadGuy mutant = badGuys["mutant"];
Debug.Log(mutant);En este ejemplo, insertamos un
string y tenemos el retorno correspondiente,
BadGuy.
Si se provee una clave, pero tal clave no existe en el diccionario, va a lanzar una excepción. Por lo tanto, si no hay garantía de que la clave exista, es mejor usar el método
TryGetValue().
if(badGuys.TryGetValue("birds", out temp))
{
// success
}
else
{
// failure
}Este método tiene un parámetro del tipo de la clave y un parámetro
out del tipo del valor. Regresa
true o verdadero si la clave pasada en el primer parámetro existe, Mientras que este es un método más seguro para regresar un valor de un diccionario, es un poco más lento que hacer una referencia directa a la clave específica.
Para ser más eficiente, usa la clave dentro de los corchetes, pero solo cuando la clave específica está definitivamente en el diccionario.
Gist del proyectoApoya el contenido de mi blog a través de:
Fuente: