簡體   English   中英

如何將Comparer用於HashSet

[英]How to use Comparer for a HashSet

由於我在這里問的另一個問題,我想為我的對象使用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
   }

}

我更喜歡有一個函數(或嵌套類[可能是單例?],如果需要)作為類同義詞的PART而不是另一個(獨立)類。 這可能嗎?

關於用法:因為我之前從未使用過這種東西,我想我必須在類同義詞中寫一個Find(字符串NameSynonym)函數,但是我應該怎么做呢?

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

在上面的代碼中,我不知道如何實現'Find'方法。 我該怎么做?

任何幫助將不勝感激(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不拋出一個異常關鍵是沒有找到(和返回鍵是否找到); 映射值在out參數中“返回”。

完全廢棄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)),因此如果查找時間對您很重要,則Dictionary會為您提供O(1)查找時間。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM