12

由于我在这里提出的另一个问题,我想为我的对象使用 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 的一部分,而不是另一个(独立)类。这可能吗?

关于用法:因为我之前从未使用过这种东西,所以我想我必须在 Synonym 类中编写一个 Find(string 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);
    }
 }

在上面的代码中,我不知道如何实现“查找”方法。我该怎么做?

任何帮助将不胜感激(PS如果我关于如何实施的想法完全错误,请告诉我并告诉我如何实施)

4

3 回答 3

19

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

请注意,上面的代码中有一些问题,关于您希望它在各种情况下如何表现。你需要弄清楚你想要它做什么

EDIT: If you want to be able to store multiple stocks for a single synonym, you effectively want a Lookup<string, Stock> - but that's immutable. You're probably best storing a Dictionary<string, List<Stock>>; a list of stocks for each string.

In terms of not throwing an error from Find, you should look at Dictionary.TryGetValue which doesn't throw an exception if the key isn't found (and also returns whether or not the key was found); the mapped value is "returned" in an out parameter.

于 2009-06-21T09:01:58.117 回答
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) 
    {
        ...
    }
于 2009-06-21T08:28:28.747 回答
0

您始终可以使用 LINQ 进行查找:

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

但是,您是否考虑过使用 Dictionary 代替,我相信它更适合提取单个成员,并且您仍然可以根据您选择的键保证没有重复项。

我不确定查找时间是 SingleOrDefault,但我很确定它是线性的 (O(n)),所以如果查找时间对您很重要,字典将为您提供 O(1) 查找时间。

于 2009-06-21T08:28:45.000 回答