Frage

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

Da ist ein SortedList Das ist gut für einen einzelnen Wert (z. B. Häufigkeit), sodass ich ihn wieder dem Wort zuordnen möchte.

SortedDictionary Bestellungen nach Schlüssel, nicht nach Wert.Einige greifen auf a zurück benutzerdefinierte Klasse, aber gibt es einen saubereren Weg?

War es hilfreich?

Lösung

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 die Lambda-Syntax vereinfachen – es ist gleichwertig, aber kürzer.Wenn Sie auf .NET 2.0 abzielen, können Sie diese Syntax nur verwenden, wenn Sie den Compiler von Visual Studio 2008 (oder höher) verwenden.

var myList = aDictionary.ToList();

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

Andere Tipps

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, da Sie die Top 10, 20, 10 % usw. auswählen können.Oder wenn Sie Ihren Worthäufigkeitsindex für verwenden type-ahead, könnten Sie auch einbeziehen StartsWith Klausel auch.

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

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

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

Dies ist die sauberste Methode, die ich je gesehen habe, und ähnelt der Ruby-Methode zum Umgang mit Hashes.

Sie können ein Wörterbuch nach Wert sortieren und es wieder in sich selbst speichern (so dass die Werte bei einer Foreach-Operation in der richtigen Reihenfolge ausgegeben werden):

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

Sicherlich ist es vielleicht nicht richtig, aber es funktioniert.

Auf hoher Ebene haben Sie keine andere Wahl, als das gesamte Wörterbuch durchzugehen 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);
    }
);

Ein Wörterbuch würde man sowieso nie sortieren können.Sie sind nicht wirklich bestellt.Die Garantien für ein Wörterbuch bestehen darin, dass die Schlüssel- und Wertesammlungen iterierbar sind und Werte nach 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.

Einträge im Wörterbuch werden nicht sortiert.Die Wörterbuchklasse in .NET ist als Hashtabelle implementiert – diese Datenstruktur ist per Definition nicht sortierbar.

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 dennoch nach Häufigkeit sortieren und in eine neue Sammlung einfügen, sortiert nach dem relevanten Feld (Häufigkeit).In dieser Sammlung sind also die Häufigkeiten Schlüssel und Wörter Werte.Da viele Wörter die gleiche Häufigkeit haben können (und Sie diese als Schlüssel verwenden), 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 (mehr Felder) hätten und Sie in der Lage sein müssten, mithilfe mehrerer verschiedener Felder als Schlüssel effizient auf sie zuzugreifen/sie zu sortieren, würden Sie wahrscheinlich eine benutzerdefinierte Datenstruktur benötigen, die aus dem Hauptspeicher besteht unterstützt das Einfügen und Entfernen von O(1) (LinkedList) und mehrere Indexierungsstrukturen – Dictionaries/SortedDictionaries/SortedLists.Diese Indizes würden eines der Felder Ihrer komplexen Klasse als Schlüssel und einen Zeiger/Referenz auf den LinkedListNode in der LinkedList als Wert verwenden.

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 dann gerechtfertigt, wenn Sie eine umfangreiche Suchverarbeitung durchführen möchten.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);
}
Dictionary<string, string> dic= new Dictionary<string, string>();
var ordered = dic.OrderBy(x => x.Value);
return ordered.ToDictionary(t => t.Key, t => t.Value);

Oder zum Spaß könnten Sie einige nützliche LINQ-Erweiterungen 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));

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 Schlüssel zu einem Wörterbuch hinzu und sortiert sie dann nach ihren Werten.Denken Sie daran, dass Dictionary-Instanzen zunächst in keiner Weise sortiert sind.Wir verwenden das LINQ-Schlüsselwort orderby in einer Abfrageanweisung.

OrderBy -Klauselprogramm mit dem Wörterbuch [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

Sortieren a SortedDictionary Liste zum Einbinden in eine ListView Steuerung 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>

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

//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 Will enthält die sortierte Version von sections

Die anderen Antworten sind gut, wenn Sie lediglich eine „temporäre“ Liste nach Wert sortiert haben möchten.Wenn Sie jedoch ein Wörterbuch sortiert haben möchten Key Das automatisch synchronisiert mit einem anderen Wörterbuch, das sortiert ist Value, du könntest das verwenden Bijection<K1, K2> Klasse.

Bijection<K1, K2> ermöglicht es Ihnen, die Sammlung mit zwei vorhandenen Wörterbüchern zu 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 verwenden dict wie jedes normale Wörterbuch (es implementiert IDictionary<K, V>) und dann anrufen dict.Inverse um das „inverse“ Wörterbuch zu erhalten, nach dem sortiert wird Value.

Bijection<K1, K2> ist ein Teil von Loyc.Collections.dll, aber wenn Sie möchten, können Sie die einfach kopieren Quellcode in Ihr eigenes Projekt.

Notiz:Falls mehrere Schlüssel mit demselben Wert vorhanden sind, können Sie sie nicht verwenden Bijection, aber Sie könnten manuell zwischen einem gewöhnlichen synchronisieren Dictionary<Key,Value> und ein BMultiMap<Value,Key>.

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) Sie können verwenden 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);
        }

In C#haben Sie in C#keine Sort () -Methoden, da Sie mehr an Sortieren nach Werten interessiert sind. Sie können Werte nicht erhalten, bis Sie ihnen den Schlüssel angeben. Kurz gesagt, Sie müssen sie durch die Reihenfolge von Linq iterieren, indem Sie von.

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
}

Du kannst einen Trick machen,

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

oder

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 einzeln (wie String, Int) oder mehrfach (wie Liste, Array, benutzerdefinierte Klasse),
Wenn es sich um eine einzelne handelt, können Sie eine Liste davon erstellen und dann die Sortierung anwenden.
Wenn die Benutzerklasse definiert ist, muss diese Klasse iCtracable implementieren,
ClassName: IComparable<ClassName> und überschreiben compareTo(ClassName c)da sie schneller als LINQ und objektorientierter sind.

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

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

Vorausgesetzt, Sie haben ein Wörterbuch, können Sie diese mithilfe der folgenden Zeile direkt nach Werten sortieren:

var x = (from c in dict orderby c.Value.Order ascending select c).ToDictionary(c => c.Key, c=>c.Value);
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top