c# - Wie sortiert man ein Wörterbuch nach Wert?

Translate

Ich muss oft ein Wörterbuch, bestehend aus Schlüsseln und Werten, nach Wert sortieren. Zum Beispiel habe ich einen Hash von Wörtern und entsprechenden Frequenzen, die ich nach Häufigkeit ordnen möchte.

Da ist einSortedListDas ist gut für einen einzelnen Wert (z. B. Frequenz), den ich dem Wort wieder zuordnen möchte.

SortedDictionaryBestellungen nach Schlüssel, nicht nach Wert. Einige greifen auf abenutzerdefinierte Klasse, aber gibt es einen saubereren Weg?

This question and all comments follow the "Attribution Required."

Alle Antworten

Translate

Verwenden:

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

Da Sie auf .NET 2.0 oder höher abzielen, können Sie dies in Lambda-Syntax vereinfachen - es ist äquivalent, aber kürzer. Wenn Sie auf .NET 2.0 abzielen, können Sie diese Syntax nur verwenden, wenn Sie den Compiler aus Visual Studio 2008 (oder höher) verwenden.

var myList = aDictionary.ToList();

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

Verwenden Sie 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;

Dies würde auch eine große Flexibilität ermöglichen, indem Sie die Top 10, 20 10% usw. auswählen können. Oder wenn Sie Ihren Worthäufigkeitsindex für verwendentype-aheadkönnten Sie auch einschließenStartsWithKlausel auch.

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

Wenn wir uns umschauen und einige C # 3.0-Funktionen verwenden, können wir dies tun:

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

Dies ist die sauberste Art, die ich gesehen habe, und ähnelt der Ruby-Art, mit Hashes umzugehen.

Quelle
Translate

Sie können ein Wörterbuch nach Wert sortieren und in sich selbst speichern (sodass die Werte in der angegebenen Reihenfolge angezeigt werden, wenn Sie darüber nachdenken):

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

Sicher, es ist vielleicht nicht richtig, aber es funktioniert.

Quelle
Translate

Auf einer hohen Ebene haben Sie keine andere Wahl, als durch das gesamte Wörterbuch zu gehen und sich jeden Wert anzusehen.

Vielleicht hilft das:http://bytes.com/forum/thread563638.htmlKopieren / Einfügen von John 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);
    }
);
Quelle
Translate

Sie würden sowieso nie in der Lage sein, ein Wörterbuch zu sortieren. Sie sind eigentlich nicht bestellt. Die Garantien für ein Wörterbuch bestehen darin, dass die Schlüssel- und Wertsammlungen iterierbar sind und Werte per Index oder Schlüssel abgerufen werden können, es gibt jedoch keine Garantie für eine bestimmte Reihenfolge. Daher müssten Sie das Name-Wert-Paar in eine Liste aufnehmen.

Quelle
Translate

Sie sortieren keine Einträge im Wörterbuch. Die Wörterbuchklasse in .NET ist als Hashtabelle implementiert - diese Datenstruktur kann nicht per Definition sortiert werden.

Wenn Sie in der Lage sein müssen, Ihre Sammlung (nach Schlüssel) zu durchlaufen, müssen Sie SortedDictionary verwenden, das als binärer Suchbaum implementiert ist.

In Ihrem Fall ist die Quellstruktur jedoch irrelevant, da sie nach einem anderen Feld sortiert ist. Sie müssten es weiterhin nach Häufigkeit sortieren und in eine neue Sammlung einfügen, die nach dem entsprechenden Feld (Häufigkeit) sortiert ist. In dieser Sammlung sind die Frequenzen Schlüssel und Wörter Werte. Da viele Wörter dieselbe Häufigkeit haben können (und Sie sie als Schlüssel verwenden werden), können Sie weder Dictionary noch SortedDictionary verwenden (sie erfordern eindeutige Schlüssel). Dadurch erhalten Sie eine SortedList.

Ich verstehe nicht, warum Sie darauf bestehen, einen Link zum Originalelement in Ihrem Haupt- / Erstwörterbuch beizubehalten.

Wenn die Objekte in Ihrer Sammlung eine komplexere Struktur hätten (mehr Felder) und Sie effizient auf sie zugreifen / sie sortieren müssten, indem Sie mehrere verschiedene Felder als Schlüssel verwenden, benötigen Sie wahrscheinlich eine benutzerdefinierte Datenstruktur, die aus dem Hauptspeicher besteht unterstützt das Einfügen und Entfernen von O (1) (LinkedList) und verschiedene Indexierungsstrukturen - Dictionaries / SortedDictionaries / SortedLists. Diese Indizes verwenden eines der Felder aus Ihrer komplexen Klasse als Schlüssel und einen Zeiger / Verweis auf den LinkedListNode in der LinkedList als Wert.

Sie müssten Einfügungen und Entfernungen koordinieren, um Ihre Indizes mit der Hauptsammlung (LinkedList) synchron zu halten, und Entfernungen wären meiner Meinung nach ziemlich teuer. Dies ähnelt der Funktionsweise von Datenbankindizes - sie eignen sich hervorragend für Suchvorgänge, werden jedoch zu einer Belastung, wenn Sie viele Einfügungen und Löschungen durchführen müssen.

All dies ist nur gerechtfertigt, wenn Sie eine nachschlagende Verarbeitung durchführen. Wenn Sie sie nur einmal nach Häufigkeit sortiert ausgeben müssen, können Sie einfach eine Liste von (anonymen) Tupeln erstellen:

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);
}
Quelle
Translate
Dictionary<string, string> dic= new Dictionary<string, string>();
var ordered = dic.OrderBy(x => x.Value);
return ordered.ToDictionary(t => t.Key, t => t.Value);
Quelle
Translate

Oder zum Spaß könnten Sie einige LINQ-Erweiterungsgüte verwenden:

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));
Quelle
Translate

Werte sortieren

Dies zeigt, wie die Werte in einem Wörterbuch sortiert werden. Wir sehen ein Konsolenprogramm, das Sie in Visual Studio kompilieren und ausführen können. Es fügt einem Wörterbuch Schlüssel hinzu und sortiert sie dann nach ihren Werten. Denken Sie daran, dass Wörterbuchinstanzen anfangs in keiner Weise sortiert sind. Wir verwenden das Schlüsselwort LINQ orderby in einer Abfrageanweisung.

OrderBy-Klauselprogramm zum Sortieren des Wörterbuchs [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;
    }
}

Ausgabe

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

Sortieren aSortedDictionaryListe zum Binden in eineListViewSteuerung mit 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>
Quelle
Translate

Der einfachste Weg, ein sortiertes Wörterbuch zu erhalten, ist die Verwendung des integrierten WörterbuchsSortedDictionaryKlasse:

//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);
}

sortedSectionswill enthält die sortierte Version vonsections

Quelle
Translate

Die anderen Antworten sind gut, wenn Sie nur eine "temporäre" Liste nach Wert sortieren möchten. Wenn Sie jedoch ein Wörterbuch sortieren möchtenKeyDaswird automatisch synchronisiertmit einem anderen Wörterbuch, das sortiert ist nachValuekönnten Sie die verwendenBijection<K1, K2>Klasse.

Bijection<K1, K2>Mit dieser Option können Sie die Sammlung mit zwei vorhandenen Wörterbüchern initialisieren. Wenn Sie also möchten, dass eines davon unsortiert und das andere sortiert wird, können Sie Ihre Bijektion mit Code wie erstellen

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

Sie können verwendendictwie jedes normale Wörterbuch (es implementiertIDictionary<K, V>) und dann anrufendict.Inverseum das "inverse" Wörterbuch zu erhalten, das nach sortiert istValue.

Bijection<K1, K2>ist ein Teil vonLoyc.Collections.dll, aber wenn Sie möchten, können Sie einfach die kopierenQuellcodein Ihr eigenes Projekt.

Hinweis: Falls es mehrere Schlüssel mit demselben Wert gibt, können Sie diese nicht verwendenBijection, aber Sie könnten manuell zwischen einem normalen synchronisierenDictionary<Key,Value>und einBMultiMap<Value,Key>.

Quelle
Translate

Angenommen, wir haben ein Wörterbuch als

   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) können Sie verwendentemporary 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);
        }
Quelle
Translate

Tatsächlich haben Wörterbücher in C # keine sort () -Methoden, da Sie mehr an der Sortierung nach Werten interessiert sind. Sie können keine Werte abrufen, bis Sie ihnen den Schlüssel geben. Kurz gesagt, Sie müssen sie mithilfe von LINQs Order By durchlaufen.

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
}

Sie können einen Trick machen,

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

or

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

Es hängt auch davon ab, welche Art von Werten Sie speichern.
ist es einfach (wie string, int) oder mehrfach (wie List, Array, benutzerdefinierte Klasse),
Wenn Sie Single sind, können Sie eine Liste erstellen und dann sortieren.
Wenn eine benutzerdefinierte Klasse vorhanden ist, muss diese Klasse IComparable implementieren.
ClassName: IComparable<ClassName>und überschreibencompareTo(ClassName c)da sie schneller als LINQ und objektorientierter sind.

Quelle
Translate

Sie können das Wörterbuch nach Wert sortieren und das Ergebnis im Wörterbuch mit dem folgenden Code abrufen:

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

Wenn Sie über ein Wörterbuch verfügen, können Sie diese direkt nach Werten sortieren, indem Sie einen einzigen Liner verwenden:

var x = (from c in dict orderby c.Value.Order ascending select c).ToDictionary(c => c.Key, c=>c.Value);
Quelle