[英]How to use a custom comparer for EqualityComparer<T>.Default?
[英]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.