由于我在这里问的另一个问题,我想为我的对象使用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如果我对如何实施它的想法完全错误,请告诉我如何实施)
答案 0 :(得分:15)
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
如果找不到密钥则不会抛出异常(并且还会返回密钥< em> 找到了);映射的值在out参数中“返回”。
答案 1 :(得分:1)
完全废弃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)
{
...
}
答案 2 :(得分:0)
您始终可以使用LINQ进行查找:
public Synonym Find(string NameSynomym)
{
return ListOfSynonyms.SingleOrDefault(x => x.Name == NameSynomym);
}
但是,您是否考虑使用词典,我相信它更适合提取单个成员,并且您仍然可以保证根据您选择的键没有重复项。
我不确定查找时间是否为SingleOrDefault,但我很确定它是线性的(O(n)),因此如果查找时间对您很重要,则Dictionary会为您提供O(1)查找时间