Domanda

Come risultato di un'altra domanda che ho posto qui, voglio usare un HashSet per i miei oggetti

Creerò oggetti contenenti una stringa e un riferimento al suo proprietario.

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

Capisco di aver bisogno di un comparatore, ma non l'ho mai usato prima. Devo creare una classe separata? come:

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
   }

}

Preferisco avere una funzione (o classe nidificata [forse un singleton?] se richiesto) essendo PARTE della classe Sinonimo invece di un'altra classe (indipendente). È possibile?

Informazioni sull'uso: Dato che non avevo mai usato questo genere di cose prima di supporre che dovessi scrivere una funzione Trova (nome stringa) all'interno della classe Synonym, ma come dovrei farlo?

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);
    }
 }

Nel codice sopra non so come implementare il metodo "Trova". Come dovrei farlo?

Qualsiasi aiuto sarà apprezzato (PS Se le mie idee su come dovrebbe essere implementato sono completamente sbagliate fammi sapere e dimmi come implementare)

È stato utile?

Soluzione

Un HashSet non ha bisogno di un IComparer<T> - ha bisogno di un IEqualityComparer<T>, come

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);

   }
}

Tuttavia, il tuo codice attuale viene compilato solo perché stai creando una serie di comparatori anziché una serie di sinonimi .

Inoltre, non penso che tu voglia davvero un set. Mi sembra che tu voglia un dizionario o una ricerca in modo da poter trovare i sinonimi di un determinato nome:

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];
    }
}

Nota che ci sono alcune domande nel codice sopra, su come vuoi che si comporti in vari casi. Devi elaborare esattamente cosa vuoi che faccia.

MODIFICA: se vuoi essere in grado di memorizzare più scorte per un singolo sinonimo, efficacemente vuoi un Lookup<string, Stock> - ma è immutabile. Probabilmente stai memorizzando meglio un Dictionary<string, List<Stock>>; un elenco di titoli per ogni stringa.

In termini di non generare un errore da Find, dovresti guardare Dictionary.TryGetValue che non genera un'eccezione se la chiave non viene trovata (e restituisce anche se la chiave era o meno trovato); il valore mappato è " restituito " in un parametro out.

Altri suggerimenti

Non sarebbe più ragionevole eliminare completamente la classe Synonym e avere un elenco di sinonimi da Dictonary (o, se esiste, HashDictionary) di stringhe?

(Non ho molta familiarità con i tipi C #, ma spero che questo trasmetta un'idea generale)

La risposta che raccomando (modificata, ora rispetta il 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) 
    {
        ...
    }

Puoi sempre usare LINQ per fare la ricerca:

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

Ma hai preso in considerazione l'utilizzo di un dizionario, credo che sia più adatto per l'estrazione di singoli membri e puoi comunque garantire che non ci siano duplicati in base alla chiave scelta.

Non sono sicuro che il tempo di ricerca sia di SingleOrDefault, ma sono abbastanza sicuro che sia lineare (O (n)), quindi se il tempo di ricerca è importante per te, un dizionario ti fornirà il tempo di ricerca O (1) .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top