Вопрос

В результате другого вопроса, который я задал здесь, я хочу использовать HashSet для своих объектов.

Я создам объекты, содержащие строку и ссылку на ее владельца.

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

Я понимаю, что мне нужен компаратор, но никогда раньше им не пользовался.Стоит ли создавать отдельный класс?нравиться:

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
   }

}

Я предпочитаю, чтобы функция (или вложенный класс [может быть, одноэлементный?] если требуется) была ЧАСТЬЮ класса Synonym, а не другого (независимого) класса.Это возможно?

Об использовании:Поскольку я никогда раньше не использовал подобные вещи, я полагаю, что мне нужно написать функцию Find(string NameSynonym) внутри класса Synonym, но как мне это сделать?

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

В приведенном выше коде я не знаю, как реализовать метод «Найти».Как мне это сделать?

Любая помощь будет оценена (PS Если мои идеи о том, как это должно быть реализовано полностью неверны, дайте мне знать и скажите, как реализовать)

Это было полезно?

Решение

HashSet не нуждается в IComparer<T> - для этого нужен IEqualityComparer<T>, такой как

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

   }
}

Однако ваш текущий код компилируется только потому, что вы создаете набор сравнивающие а не набор синонимы.

Более того, я не думаю, что вам вообще нужен набор.Мне кажется, вам нужен словарь или поиск, чтобы найти синонимы для данного имени:

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

Обратите внимание, что в приведенном выше коде есть несколько вопросов о том, как вы хотите, чтобы он вел себя в различных случаях.Вам нужно потренироваться точно что вы хотите, чтобы он сделал.

РЕДАКТИРОВАТЬ:Если вы хотите иметь возможность хранить несколько акций для одного синонима, вы эффективно хотеть Lookup<string, Stock> - но это неизменно.Вы, вероятно, лучше всего храните Dictionary<string, List<Stock>>;список акций для каждой строки.

С точки зрения того, чтобы не выдавать ошибку из Find, вам стоит посмотреть Dictionary.TryGetValue который не генерирует исключение, если ключ не найден (а также возвращает, является ли ключ был найденный);сопоставленное значение «возвращается» в выходном параметре.

Другие советы

Не разумнее ли было бы отказаться от Synonym класс полностью и иметь список синонимов, чтобы быть Dictonary (или, если такое есть, HashDictionary) струн?

(Я не очень знаком с типами C#, но надеюсь, что это передает общую идею)

Ответ, который я рекомендую (отредактировано, теперь учитывает случай):

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

Вы всегда можете использовать LINQ для поиска:

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

Но рассматривали ли вы вместо этого использование словаря? Я считаю, что он лучше подходит для извлечения отдельных членов, и вы все равно можете гарантировать отсутствие дубликатов на основе выбранного вами ключа.

Я не уверен, что время поиска равно SingleOrDefault, но я почти уверен, что оно линейно (O(n)), поэтому, если время поиска важно для вас, словарь предоставит вам время поиска O(1).

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top