Question

Suite à une autre question que j'ai posée ici, je souhaite utiliser un hachage pour mes objets

Je créerai des objets contenant une chaîne et une référence à son propriétaire.

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

Je comprends qu'il me faut un comparateur, mais je ne l'ai jamais utilisé auparavant. Devrais-je créer une classe séparée? comme:

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
   }

}

Je préfère avoir une fonction (ou une classe imbriquée [peut-être un singleton?] si nécessaire) faisant partie de la classe Synonym au lieu d'une autre classe (indépendante). Est-ce possible?

À propos de l'utilisation: Comme je n’avais jamais utilisé ce genre de chose auparavant, je suppose que je dois écrire une fonction Find (string NameSynonym) dans la classe Synonym, mais comment dois-je faire cela?

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

Dans le code ci-dessus, je ne sais pas comment implémenter la méthode "Rechercher". Comment dois-je faire cela?

Toute aide sera appréciée (PS Si mes idées sur la manière de le mettre en œuvre sont complètement fausses, faites-le-moi savoir et dites-moi comment le mettre en œuvre)

Était-ce utile?

La solution

Un HashSet n'a pas besoin d'un IComparer<T> - il a besoin d'un IEqualityComparer<T>, tel que

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

   }
}

Toutefois, votre code actuel ne compile que parce que vous créez un ensemble de comparateurs plutôt qu'un ensemble de synonymes .

De plus, je ne pense pas que vous souhaitiez vraiment un ensemble. Il me semble que vous voulez un dictionnaire ou une recherche pour pouvoir trouver les synonymes d'un nom donné:

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

Notez que le code ci-dessus contient des questions sur la manière dont vous voulez qu'il se comporte dans divers cas. Vous devez définir exactement ce que vous voulez qu'il fasse.

MODIFIER: si vous souhaitez pouvoir stocker plusieurs actions pour un même synonyme, vous voulez réellement un Lookup<string, Stock> - mais c'est immuable. Il est probablement préférable de stocker un Dictionary<string, List<Stock>>; une liste des stocks pour chaque chaîne.

Pour éviter de générer une erreur de Find, vous devez rechercher Dictionary.TryGetValue qui ne génère pas d'exception si la clé n'est pas trouvée (et indique également si la clé était ou non trouvé); la valeur mappée est " renvoyé " dans un paramètre de sortie.

Autres conseils

Ne serait-il pas plus raisonnable de supprimer entièrement la Synonym classe et de faire en sorte que la liste des synonymes soit un Dictonary (ou, s'il existe, HashDictionary) des chaînes?

(Je ne connais pas très bien les types C #, mais j'espère que cela donne une idée générale)

La réponse que je recommande (modifiée, respecte désormais le cas):

    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) 
    {
        ...
    }

Vous pouvez toujours utiliser LINQ pour effectuer la recherche:

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

Mais, avez-vous envisagé d'utiliser un dictionnaire à la place, je pense qu'il est mieux adapté à l'extraction de membres individuels et vous pouvez toujours garantir qu'il n'y a pas de doublons basés sur la clé que vous choisissez.

Je ne suis pas sûr que le temps de recherche soit de SingleOrDefault, mais je suis assez sûr qu'il est linéaire (O (n)). Par conséquent, si le temps de recherche est important pour vous, un dictionnaire vous fournira le temps de recherche O (1). .

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top