Pregunta

Como resultado de otra pregunta que hice aquí, quiero usar un HashSet para mis objetos

Crearé objetos que contengan una cadena y una referencia a su propietario.

public class Synonym
{
   private string name;
   private Stock owner;
   public Stock(string NameSynonym, Stock stock)
   {
       name=NameSynonym;
       owner=stock
   }
   // [+ 'get' for 'name' and 'owner']
}

Entiendo que necesito un comparador, pero nunca lo usé antes. ¿Debo crear una clase separada? como:

public class SynonymComparer : IComparer<Synonym>
{
   public int Compare(Synonym One, Synonym Two)
   { // Should I test if 'One == null'  or  'Two == null'  ???? 
       return String.Compare(One.Name, Two.Name, true); // Caseinsesitive
   }

}

Prefiero tener una función (o una clase anidada [¿tal vez un singleton?] si es necesario) que sea PARTE del sinónimo de clase en lugar de otra clase (independiente). ¿Es esto posible?

Sobre el uso: Como nunca he usado este tipo de cosas antes, supongo que debo escribir una función Find (string NameSynonym) dentro de Class Synonym, pero ¿cómo debo hacer eso?

public class SynonymManager
{ 
    private HashSet<SynonymComparer<Synonym>> ListOfSynonyms;

    public SynonymManager()
    {
        ListOfSymnonyms = new HashSet<SynonymComparer<Synonym>>();
    }

    public void SomeFunction()
    { // Just a function to add 2 sysnonyms to 1 stock
        Stock stock = GetStock("General Motors");
        Synonym otherName = new Synonym("GM", stock);
        ListOfSynonyms.Add(otherName);
        Synonym otherName = new Synonym("Gen. Motors", stock);
        ListOfSynonyms.Add(otherName);
    }

    public Synonym Find(string NameSynomym)
    {
       return ListOfSynonyms.??????(NameSynonym);
    }
 }

En el código anterior, no sé cómo implementar el método 'Buscar'. ¿Cómo debo hacer eso?

Cualquier ayuda será apreciada (PD: si mis ideas sobre cómo debería implementarse son completamente erróneas, hágamelo saber y dígame cómo implementarlas)

¿Fue útil?

Solución

Un HashSet no necesita un IComparer<T>, necesita un IEqualityComparer<T>, como

public class SynonymComparer : IEqualityComparer<Synonym>      
{
   public bool Equals(Synonym one, Synonym two)
   {
        // Adjust according to requirements.
        return StringComparer.InvariantCultureIgnoreCase
                             .Equals(one.Name, two.Name);

   }

   public int GetHashCode(Synonym item)
   {
        return StringComparer.InvariantCultureIgnoreCase
                             .GetHashCode(item.Name);

   }
}

Sin embargo, su código actual solo se compila porque está creando un conjunto de comparadores en lugar de un conjunto de sinónimos .

Además, no creo que realmente quieras un set en absoluto. Me parece que quiere un diccionario o una búsqueda para poder encontrar los sinónimos de un nombre dado:

public class SynonymManager
{ 
    private readonly IDictionary<string, Synonym> synonyms = new
        Dictionary<string, Synonym>();

    private void Add(Synonym synonym)
    {
        // This will overwrite any existing synonym with the same name.
        synonyms[synonym.Name] = synonym;
    }

    public void SomeFunction()
    { 
        // Just a function to add 2 synonyms to 1 stock.
        Stock stock = GetStock("General Motors");
        Synonym otherName = new Synonym("GM", stock);
        Add(otherName);
        ListOfSynonyms.Add(otherName);
        otherName = new Synonym("Gen. Motors", stock);
        Add(otherName);
    }

    public Synonym Find(string nameSynonym)
    {
       // This will throw an exception if you don't have
       // a synonym of the right name.  Do you want that?
       return synonyms[nameSynonym];
    }
}

Tenga en cuenta que hay algunas preguntas en el código anterior, sobre cómo desea que se comporte en varios casos. Debe calcular exactamente lo que quiere que haga.

EDITAR: si desea poder almacenar múltiples acciones para un solo sinónimo, efectivamente quiere un Lookup<string, Stock>, pero eso es inmutable. Probablemente sea mejor almacenar un Dictionary<string, List<Stock>>; una lista de acciones para cada cadena.

En términos de no arrojar un error de Find, debe mirar Dictionary.TryGetValue que no arroja una excepción si no se encuentra la clave (y también devuelve si la clave era o no encontrado); el valor asignado es " devuelto " en un parámetro de salida.

Otros consejos

¿No sería más razonable desechar la clase Synonym por completo y tener una lista de sinónimos para ser un Dictonary (o, si existe tal cosa, HashDictionary) de cadenas?

(No estoy muy familiarizado con los tipos de C #, pero espero que esto transmita una idea general)

La respuesta que recomiendo (editado, ahora respeta el caso):

    IDictionary<string, Stock>>  ListOfSynonyms = new Dictionary<string,Stock>>(); 
    IDictionary<string, string>> ListOfSynForms = new Dictionary<string,string>>(); 
    class Stock 
    {   
        ...
        Stock addSynonym(String syn) 
        {
            ListOfSynForms[syn.ToUpper()] = syn;
            return ListOfSynonyms[syn.ToUpper()] = this;
        }
        Array findSynonyms()
        {
            return ListOfSynonyms.findKeysFromValue(this).map(x => ListOfSynForms[x]);
        }
    }

    ...
    GetStock("General Motors").addSynonym('GM').addSynonym('Gen. Motors');
    ...
    try  
    {
        ... ListOfSynonyms[synonym].name ...
    }  
    catch (OutOfBounds e) 
    {
        ...
    } 
    ...
    // output everything that is synonymous to GM. This is mix of C# and Python
    ... GetStock('General Motors').findSynonyms()
    // test if there is a synonym
    if (input in ListOfSynonyms) 
    {
        ...
    }

Siempre puedes usar LINQ para hacer la búsqueda:

public Synonym Find(string NameSynomym)
{
   return ListOfSynonyms.SingleOrDefault(x => x.Name == NameSynomym);
}

Pero, si ha considerado usar un Diccionario, creo que es más adecuado para extraer miembros individuales, y aún puede garantizar que no haya duplicados en función de la clave que elija.

No estoy seguro de que el tiempo de búsqueda sea SingleOrDefault, pero estoy bastante seguro de que es lineal (O (n)), por lo que si el tiempo de búsqueda es importante para usted, un Diccionario le proporcionará el tiempo de búsqueda O (1) .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top