ما هي أسرع طريقة لإنشاء مجموعة فريدة من نوعها في .صافي 2

StackOverflow https://stackoverflow.com/questions/232997

سؤال

لدي ما هو أساسا خشنة مجموعة من أزواج قيمة اسم - أنا بحاجة إلى إنشاء مجموعة فريدة من نوعها اسم القيم من هذا.خشنة مجموعة تقريبا 86,000 × 11 القيم.لا يهم بالنسبة لي ما الطريقة لتخزين قيمة اسم الزوج (سلسلة واحدة "name=القيمة" أو متخصص من الدرجة على سبيل المثال keyvaluepair العلامة).
معلومات إضافية: هناك 40 متميزة أسماء عدد أكبر من قيم مميزة - ربما في المنطقة 10,000 القيم.

أنا باستخدام C#.NET 2.0 (و أداء ضعيف جدا وأنا أفكر أنه قد يكون من الأفضل دفع كامل خشنة مجموعة إلى قاعدة بيانات sql و لا نخبة متميزة من هناك).

أدناه هو القانون الحالي Im باستخدام:

List<List<KeyValuePair<string,string>>> vehicleList = retriever.GetVehicles();
this.statsLabel.Text = "Unique Vehicles: " + vehicleList.Count;

Dictionary<KeyValuePair<string, string>, int> uniqueProperties = new Dictionary<KeyValuePair<string, string>, int>();
foreach (List<KeyValuePair<string, string>> vehicle in vehicleList)
{
    foreach (KeyValuePair<string, string> property in vehicle)
    {
        if (!uniqueProperties.ContainsKey(property))
        {
            uniqueProperties.Add(property, 0);
        }
    }
}
this.statsLabel.Text += "\rUnique Properties: " + uniqueProperties.Count;
هل كانت مفيدة؟

المحلول

لقد كان يعمل في 0.34 ثانية من 9+ دقيقة

المشكلة هي عند مقارنة keyvaluepair العلامة البنيات.عملت من حوله من خلال كتابة comparer الكائن يمر مثيل إلى القاموس.

من ما أستطيع أن تحدد ، keyvaluepair العلامة.GetHashCode() ترجع hashcode من Key كائن (في هذا المثال أقل فريدة من نوعها وجوه).

كما في القاموس يضيف (و التحقق من وجود) كل بند ، فإنه يستخدم على حد سواء يساوي GetHashCode الوظائف ، ولكن يجب أن تعتمد على تساوي دالة عند hashcode أقل فريدة من نوعها.

من خلال توفير أكثر فريدة من نوعها GetHashCode وظيفة ، excerises يساوي وظيفة أقل بكثير في كثير من الأحيان.أنا أيضا محسن يساوي وظيفة مقارنة أكثر فريدة من نوعها القيم قبل أقل أونقيوي المفاتيح.

86,000 * 11 البنود مع 10 ، 000 خصائص فريدة من نوعها يعمل في 0.34 ثانية باستخدام comparer كائن أدناه (بدون comparer كائن يستغرق 9 دقائق و 22 ثانية)

ويساعد هذا الأمل :)

    class StringPairComparer
        : IEqualityComparer<KeyValuePair<string, string>>
    {
        public bool Equals(KeyValuePair<string, string> x, KeyValuePair<string, string> y)
        {
            return x.Value == y.Value && x.Key == y.Key;
        }
        public int GetHashCode(KeyValuePair<string, string> obj)
        {
            return (obj.Key + obj.Value).GetHashCode();
        }
    }

تحرير:إذا كان مجرد سلسلة واحدة (بدلا من keyvaluepair العلامة ، حيث string = اسم+قيمة) سيكون تقريبا مرتين بسرعة.انها لطيفة إينترستينغ المشكلة ، لقد قضيت faaaaaar الكثير من الوقت على ذلك (تعلمت الهدوء قليلا على الرغم من)

نصائح أخرى

إذا كنت لا تحتاج إلى أي علاقة بين كل مفتاح/قيمة الزوج و القيم الفريدة التي تنتجينها يمكنك فقط استخدام GUID?أفترض أن المشكلة هي أنه الحالي الخاص بك 'مفتاح' ليست فريدة من نوعها في هذا خشنة مجموعة.

Dictionary<System.Guid, KeyValuePair<string, string>> myDict 
   = new Dictionary<Guid, KeyValuePair<string, string>>();


foreach of your key values in their current format
   myDict.Add(System.Guid.NewGuid(), new KeyValuePair<string, string>(yourKey, yourvalue))

يبدو أن متجر ما تحتاج ولكن أنا لا أعرف كيف يمكن سحب البيانات من هذا كما لن يكون هناك أي الدلالي العلاقة بين إنشاء Guid & ما كان في الأصل...

يمكنك تقديم أي مزيد من المعلومات في سؤالك ؟

استخدام keyvaluepair العلامة مجمع الطبقة ومن ثم إنشاء القاموس مع إنشاء مجموعة ربما ؟ أو تنفيذ الخاص بك المجمع أن يتجاوز يساوي GetHashCode.

Dictionary<KeyValuePair, bool> mySet;

for(int i = 0; i < keys.length; ++i)
{
    KeyValuePair kvp = new KeyValuePair(keys[i], values[i]);
    mySet[kvp] = true;
}

بدلا من استخدام Dictionary لماذا لا تمديد KeyedCollection<TKey, TItem>?وفقا للوثائق:

يوفر مجردة الفئة الأساسية لمجموعة الذي المفاتيح المضمنة في القيم.

ثم تحتاج إلى تجاوز protected TKey GetKeyForItem(TItem item) وظيفة.كما هو هجين بين IList<T> و IDictionary<TKey, TValue> أعتقد أنه من المحتمل أن تكون سريعة جدا.

ماذا عن:

Dictionary<NameValuePair,int> hs = new Dictionary<NameValuePair,int>();
foreach (i in jaggedArray)
{
    foreach (j in i)
    {
        if (!hs.ContainsKey(j))
        {
            hs.Add(j, 0);
        }
    }
}
IEnumerable<NameValuePair> unique = hs.Keys;

بالطبع, إذا كنت تستخدم C# 3.0, .NET framework 3.5:

var hs = new HashSet<NameValuePair>();
hs.UnionWith(jaggedArray.SelectMany(item => item));

سوف تفعل خدعة.

هل لمحة رمزك ؟ كنت متأكدا من أن foreach الحلقات هي عنق الزجاجة ، وليس المسترد.GetVehicles()?

لم تخلق اختبار صغير المشروع حيث وهمية المسترد والسماح لها بالعودة 86.000 × 11 القيم.أول محاولة لي ركض في 5 ثوان ، وخلق البيانات المدرجة.

لقد استخدمت نفس القيمة لكل مفتاح وقيمة أين المفتاح الأول كان "0#0" وآخر "85999#10".

ثم انتقلت إلى guid.نفس النتيجة.

ثم جعلت مفتاح أطول, مثل هذا:

        var s = Guid.NewGuid().ToString();
        return s + s + s + s + s + s + s+ s + s + s;

الآن استغرق الأمر ما يقرب من 10 ثوان.

ثم جعلت مفاتيح بجنون طويلة وحصلت على الخروج من الذاكرة استثناء.ليس لدي ملف المبادلة على جهاز الكمبيوتر حتى حصلت على هذا الاستثناء على الفور.

كم هي المفاتيح الخاصة بك ؟ هي الذاكرة الظاهرية استهلاك سبب سوء الأداء ؟

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top