Pergunta

Como resultado de uma outra pergunta que fiz aqui eu quero usar um HashSet para os meus objetos

Vou criar objetos que contêm uma corda e uma referência ao seu proprietário.

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

Eu compreendo que eu preciso de um comparador, mas nunca usou antes. Devo criar uma classe 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
   }

}

Eu prefiro ter uma função (ou classe aninhada [talvez um singleton?] Se necessário) ser parte da classe Sinônimo vez de outra classe (independente). Isso é possível?

Sobre o uso: Como eu nunca usei esse tipo de coisa antes Suponho que deve escrever uma função Find (string NameSynonym) dentro da classe Sinônimo, mas como eu deveria fazer isso?

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

No código acima eu não sei como implementar o método 'Find'. Como devo fazer isso?

Qualquer ajuda será apreciada (PS Se minhas idéias sobre como deve ser implementado são completamente errado me avise e me diga como implementar)

Foi útil?

Solução

Um HashSet não precisa de um IComparer<T> - ele precisa de um 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);

   }
}

No entanto, o seu código atual só compila porque você está criando um conjunto de comparadores em vez de um conjunto de sinônimos .

Além disso, eu não acho que você realmente quer um conjunto de todo. Parece-me que você quer um dicionário ou uma pesquisa para que você possa encontrar os sinônimos para um determinado 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];
    }
}

Note que existem algumas questões no código acima, sobre como você quer que ele se comporta em vários casos. Você precisa trabalhar com exatamente o que você quer que ele faça.

EDIT: Se você quer ser capaz de armazenar várias ações para um único sinônimo, você efetivamente quer um Lookup<string, Stock> - mas isso é imutável. Você provavelmente melhor está armazenando um Dictionary<string, List<Stock>>; uma lista de ações para cada string.

Em termos de não lançar um erro de Find, você deve olhar para Dictionary.TryGetValue que não lançar uma exceção se a chave não é encontrada (e também retorna ou não a tecla foi Found ); o valor mapeada é "devolvida" em um parâmetro de saída.

Outras dicas

Não seria mais razoável para desfazer a classe Synonym inteiramente e têm lista de sinônimos para ser um Dictonary (ou, se há uma coisa tal, HashDictionary) de cordas?

(Eu não sou muito familiarizado com C # tipos, mas espero que esta idéia geral transmite)

A resposta que eu recomendo (editado, agora respeita o 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) 
    {
        ...
    }

Você sempre pode usar LINQ para fazer a pesquisa:

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

Mas, você já pensou em usar um dicionário em vez disso, eu acredito que é mais adequado para a extração de membros individuais, e você ainda pode garantia de que não há duplicatas com base na chave que você escolher.

Não estou certo de que o tempo de pesquisa é de SingleOrDefault, mas eu tenho quase certeza que é linear (O (n)), por isso, se o tempo de pesquisa é importante para você, um dicionário irá fornecer-lhe O (1) lookup tempo .

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top