سؤال

أنا في كثير من الأحيان إلى نوع القاموس ، تتكون من مفاتيح وقيم من حيث القيمة.على سبيل المثال ، يجب تجزئة الكلمات و كل الترددات التي أريد أن أمر من التردد.

هناك SortedList وهو أمر جيد على قيمة واحدة (قل التردد) ، أريد أن اعرض الخريطة مرة أخرى إلى الكلمة.

SortedDictionary أوامر عن طريق مفتاح, لا قيمة.يلجأ البعض إلى فئة مخصصة, لكن هل هناك نظافة الطريق ؟

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

المحلول

استخدام:

using System.Linq.Enumerable;
...
List<KeyValuePair<string, string>> myList = aDictionary.ToList();

myList.Sort(
    delegate(KeyValuePair<string, string> pair1,
    KeyValuePair<string, string> pair2)
    {
        return pair1.Value.CompareTo(pair2.Value);
    }
);

منذ كنت تستهدف .الصافي 2.0 أو أعلى يمكنك تكرار هذا في امدا الجملة إنه ما يعادلها ، ولكن أقصر.إذا كنت تستهدف .NET 2.0 يمكنك فقط استخدام بناء الجملة هذا إذا كنت تستخدم مترجم من Visual Studio 2008 (أو أعلى).

var myList = aDictionary.ToList();

myList.Sort((pair1,pair2) => pair1.Value.CompareTo(pair2.Value));

نصائح أخرى

استخدام LINQ:

Dictionary<string, int> myDict = new Dictionary<string, int>();
myDict.Add("one", 1);
myDict.Add("four", 4);
myDict.Add("two", 2);
myDict.Add("three", 3);

var sortedDict = from entry in myDict orderby entry.Value ascending select entry;

وهذا من شأنه أيضا أن تتيح قدرا كبيرا من المرونة في ذلك يمكنك اختيار أعلى 10 20 10 ٪ ، وما إلى ذلك.أو إذا كنت تستخدم word تردد مؤشر type-ahead, هل يمكن أن تشمل أيضا StartsWith شرط كذلك.

var ordered = dict.OrderBy(x => x.Value);

أبحث في جميع أنحاء باستخدام C# 3.0 الميزات يمكننا أن نفعل هذا:

foreach (KeyValuePair<string,int> item in keywordCounts.OrderBy(key=> key.Value))
{ 
    // do something with item.Key and item.Value
}

هذا هو أنظف طريقة رأيته و هو على غرار روبي طريقة التعامل مع التجزئات.

يمكنك فرز قاموس قيمة وحفظه إلى نفسها (بحيث عند foreach أكثر من ذلك القيم في):

dict = dict.OrderBy(x => x.Value).ToDictionary(x => x.Key, x => x.Value);

بالتأكيد, قد لا تكون صحيحة ، لكنه يعمل.

على مستوى عال, لا يوجد لديك خيار آخر بعد ذلك سيرا على الأقدام من خلال القاموس كله وننظر في كل قيمة.

ربما هذا يساعد على:http://bytes.com/forum/thread563638.html نسخ/لصق من جون Timney:

Dictionary<string, string> s = new Dictionary<string, string>();
s.Add("1", "a Item");
s.Add("2", "c Item");
s.Add("3", "b Item");

List<KeyValuePair<string, string>> myList = new List<KeyValuePair<string, string>>(s);
myList.Sort(
    delegate(KeyValuePair<string, string> firstPair,
    KeyValuePair<string, string> nextPair)
    {
        return firstPair.Value.CompareTo(nextPair.Value);
    }
);

أنك لن تكون قادرة على فرز القاموس على أي حال.فهي ليست في الواقع أمر.ضمانات القاموس أن مفتاح وقيمة مجموعات iterable ، والقيم يمكن استرجاعها عن طريق الفهرس أو مفتاح, ولكن لا يوجد أي ضمان من أي ترتيب معين.ومن ثم كنت بحاجة للحصول على اسم قيمة زوج إلى قائمة.

لا فرز الإدخالات في القاموس.قاموس الطبقة .صافي نفذت hashtable - هذه البيانات هيكل ليس للفرز حسب التعريف.

إذا كنت بحاجة إلى أن تكون قادرة على تكرار عبر جمع الخاصة بك (عن طريق مفتاح) - تحتاج إلى استخدام SortedDictionary ، والتي يتم تنفيذها كما شجرة البحث الثنائية.

في الحالة الخاصة بك ، ومع ذلك المصدر هيكل غير ذي صلة ، لأنه حسب حقل مختلف.سوف لا تزال تحتاج إلى فرز تردد ووضعها في مجموعة جديدة حسب المجال ذي الصلة (تردد).حتى في هذه المجموعة الترددات مفاتيح الكلمات القيم.منذ العديد من الكلمات التي يمكن أن يكون لها نفس التردد (وأنت ذاهب إلى استخدامه بمثابة مفتاح) لا يمكنك استخدام لا قاموس ولا SortedDictionary (التي تتطلب مفاتيح فريدة من نوعها).هذا يترك لك مع SortedList.

أنا لا أفهم لماذا تصر على الحفاظ على ارتباط إلى العنصر الأصلي في الرئيسية/أول قاموس.

إذا كانت الأشياء في جمع الخاصة بك لديها بنية أكثر تعقيدا (أكثر ميادين) و تحتاج إلى أن تكون قادرة على الوصول بكفاءة/فرز لهم باستخدام عدة مجالات مختلفة مثل مفاتيح - سوف تحتاج على الأرجح مخصص بنية البيانات التي تتكون من التخزين الرئيسية التي تدعم O(1) الإدراج وإزالة (LinkedList) و العديد من الفهرسة الهياكل - القواميس/SortedDictionaries/SortedLists.هذه المؤشرات تستخدم أحد الحقول من مجمع فئة مفتاح مؤشر/إشارة إلى LinkedListNode في LinkedList كقيمة.

سوف تحتاج إلى تنسيق الإدراج وإزالة للحفاظ على فهارس متزامنا مع جمع الرئيسية (LinkedList) و الإزالة ستكون مكلفة جدا كنت أعتقد.هذا هو مماثل لكيفية قاعدة بيانات مؤشرات العمل - فهي رائعة على عمليات البحث ولكنها تصبح عبئا عندما تحتاج إلى تنفيذ العديد من insetions والحذف.

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

var dict = new SortedDictionary<string, int>();
// ToDo: populate dict

var output = dict.OrderBy(e => e.Value).Select(e => new {frequency = e.Value, word = e.Key}).ToList();

foreach (var entry in output)
{
    Console.WriteLine("frequency:{0}, word: {1}",entry.frequency,entry.word);
}
Dictionary<string, string> dic= new Dictionary<string, string>();
var ordered = dic.OrderBy(x => x.Value);
return ordered.ToDictionary(t => t.Key, t => t.Value);

أو من أجل متعة هل يمكن استخدام بعض LINQ تمديد الخير:

var dictionary = new Dictionary<string, int> { { "c", 3 }, { "a", 1 }, { "b", 2 } };
dictionary.OrderBy(x => x.Value)
  .ForEach(x => Console.WriteLine("{0}={1}", x.Key,x.Value));

نوع القيم

هذا العرض كيفية فرز القيم في القاموس.ونحن نرى وحدة البرنامج يمكنك ترجمة في Visual Studio وتشغيل.فإنه يضيف مفاتيح القاموس ثم أنواع من القيم.تذكر أن القاموس الحالات ليست في البداية فرز بأي شكل من الأشكال.ونحن استخدام LINQ orderby الكلمة في جملة الاستعلام.

OrderBy شرط برنامج أنواع القاموس [C#]

using System;
using System.Collections.Generic;
using System.Linq;

class Program
{
    static void Main()
    {
        // Example dictionary.
        var dictionary = new Dictionary<string, int>(5);
        dictionary.Add("cat", 1);
        dictionary.Add("dog", 0);
        dictionary.Add("mouse", 5);
        dictionary.Add("eel", 3);
        dictionary.Add("programmer", 2);

        // Order by values.
        // ... Use LINQ to specify sorting by value.
        var items = from pair in dictionary
                orderby pair.Value ascending
                select pair;

        // Display results.
        foreach (KeyValuePair<string, int> pair in items)
        {
            Console.WriteLine("{0}: {1}", pair.Key, pair.Value);
        }

        // Reverse sort.
        // ... Can be looped over in the same way as above.
        items = from pair in dictionary
        orderby pair.Value descending
        select pair;
    }
}

الإخراج

dog: 0
cat: 1
programmer: 2
eel: 3
mouse: 5

فرز SortedDictionary قائمة إلى ربط في ListView التحكم باستخدام VB.NET:

Dim MyDictionary As SortedDictionary(Of String, MyDictionaryEntry)

MyDictionaryListView.ItemsSource = MyDictionary.Values.OrderByDescending(Function(entry) entry.MyValue)

Public Class MyDictionaryEntry ' Need Property for GridViewColumn DisplayMemberBinding
    Public Property MyString As String
    Public Property MyValue As Integer
End Class

XAML:

<ListView Name="MyDictionaryListView">
    <ListView.View>
        <GridView>
            <GridViewColumn DisplayMemberBinding="{Binding Path=MyString}" Header="MyStringColumnName"></GridViewColumn>
            <GridViewColumn DisplayMemberBinding="{Binding Path=MyValue}" Header="MyValueColumnName"></GridViewColumn>
         </GridView>
    </ListView.View>
</ListView>

أسهل طريقة للحصول على فرز القاموس هو استخدام المدمج في SortedDictionary الدرجة:

//Sorts sections according to the key value stored on "sections" unsorted dictionary, which is passed as a constructor argument
System.Collections.Generic.SortedDictionary<int, string> sortedSections = null;
if (sections != null)
{
    sortedSections = new SortedDictionary<int, string>(sections);
}

sortedSections سوف يحتوي على فرز إصدار sections

إجابات أخرى جيدة ، إذا كان كل ما تريده هو أن يكون "مؤقت" قائمة تم فرزها حسب القيمة.ومع ذلك ، إذا كنت تريد أن يكون لها قاموس حسب Key أن مزامنة تلقائيا مع آخر القاموس أن يتم فرز حسب Value, هل يمكن استخدام Bijection<K1, K2> الدرجة.

Bijection<K1, K2> يسمح لك لتهيئة جمع مع اثنين من القواميس الموجودة, حتى إذا كنت تريد أن واحدا منهم لم يتم فرزها و تريد واحدة أخرى ليتم فرزها ، يمكنك إنشاء الخاصة بك bijection مع رمز مثل

var dict = new Bijection<Key, Value>(new Dictionary<Key,Value>(), 
                               new SortedDictionary<Value,Key>());

يمكنك استخدام dict مثل أي شخص طبيعي القاموس (تنفذ IDictionary<K, V>) ، dict.Inverse للحصول على "معكوس" القاموس الذي هو مرتبة حسب Value.

Bijection<K1, K2> هو جزء من Loyc.Collections.dll, ولكن إذا كنت تريد, يمكنك ببساطة نسخ التعليمات البرمجية المصدر في المشروع الخاص بك.

ملاحظة:في حالة وجود مفاتيح متعددة مع نفس القيمة, لا يمكنك استخدام Bijection, لكن يمكنك يدويا مزامنة بين العاديين Dictionary<Key,Value> و BMultiMap<Value,Key>.

لنفترض أن لدينا قاموس

   Dictionary<int, int> dict = new Dictionary<int, int>();
   dict.Add(21,1041);
   dict.Add(213, 1021);
   dict.Add(45, 1081);
   dict.Add(54, 1091);
   dict.Add(3425, 1061);
   sict.Add(768, 1011);

1) يمكنك استخدام temporary dictionary to store values as :

        Dictionary<int, int> dctTemp = new Dictionary<int, int>();

        foreach (KeyValuePair<int, int> pair in dict.OrderBy(key => key.Value))
        {
            dctTemp .Add(pair.Key, pair.Value);
        }

في الواقع في C#, قواميس بفضل لديهم نوع() الأساليب ، كما كنت أكثر اهتماما في نوع من القيم ، كنت غير قادر على الحصول على القيم حتى توفر لهم المفتاح ، باختصار تحتاج إلى تكرار خلال لهم ، باستخدام LINQ أمر ،

var items = new Dictionary<string, int>();
items.Add("cat", 0);
items.Add("dog", 20);
items.Add("bear", 100);
items.Add("lion", 50);

// Call OrderBy method here on each item and provide them the ids.
foreach (var item in items.OrderBy(k => k.Key))
{
    Console.WriteLine(item);// items are in sorted order
}

يمكنك أن تفعل خدعة ،

var sortedDictByOrder = items.OrderBy(v => v.Value);

أو

var sortedKeys = from pair in dictName
            orderby pair.Value ascending
            select pair;

أيضا يعتمد على أي نوع من القيم التي يتم تخزين ،
هو واحد (مثل سلسلة الباحث) أو متعددة (مثل قائمة, مجموعة, المعرفة من قبل المستخدم الطبقة) ،
إذا واحد يمكنك جعل قائمة ومن ثم تطبيق نوع.
إذا كان المستخدم تعريف الطبقة ، ثم تلك الفئة يجب أن تنفذ IComparable,
ClassName: IComparable<ClassName> و تجاوز compareTo(ClassName c) كما أنهم أكثر أسرع من LINQ و أكثر وجوه المنحى.

يمكنك فرز القاموس من حيث القيمة والحصول على النتيجة في القاموس باستخدام التعليمات البرمجية التالية:

Dictionary <<string, string>> ShareUserNewCopy = 
       ShareUserCopy.OrderBy(x => x.Value).ToDictionary(pair => pair.Key,
                                                        pair => pair.Value);                                          

ونظرا لديك قاموس يمكنك فرزها مباشرة على القيم باستخدام أقل من واحد بطانة:

var x = (from c in dict orderby c.Value.Order ascending select c).ToDictionary(c => c.Key, c=>c.Value);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top