سؤال

نتيجة لسؤال آخر طرحته هنا أريد استخدام 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
   }

}

أفضل أن تكون لدي وظيفة (أو فئة متداخلة [ربما مفردة؟] إذا لزم الأمر) لتكون جزءًا من مرادف الفئة بدلاً من فئة أخرى (مستقلة).هل هذا ممكن؟

حول الاستخدام:نظرًا لأنني لم أستخدم هذا النوع من الأشياء مطلقًا قبل أن أفترض أنه يجب علي كتابة وظيفة 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);
    }
 }

في الكود أعلاه لا أعرف كيفية تنفيذ طريقة "البحث".كيف يجب أن أفعل ذلك؟

سيكون موضع تقدير أي مساعدة (ملاحظة: إذا كانت أفكاري حول كيفية تنفيذها خاطئة تماما ، فأخبرني وأخبرني بكيفية التنفيذ)

هل كانت مفيدة؟

المحلول

لا يحتاج 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