Hoe sorteert u een woordenboek per waarde?

Ik moet vaak een woordenboek sorteren, bestaande uit sleutels en amp; waarden, per waarde. Ik heb bijvoorbeeld een hash woorden en respectieve frequenties, die ik wil bestellen op frequentie.

Er is een SortedListdie goed is voor een enkele waarde (zeg frequentie), die ik het wil in kaart brengen naar het woord.

SortedDictionary bestellingen per sleutel, geen waarde. Sommige resort naar een aangepaste klasse , maar is er een schonere manier?


Antwoord 1, Autoriteit 100%

Gebruik:

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

Aangezien u richten op .NET 2.0 of hoger, kunt u dit vereenvoudigen in Lambda-syntaxis – het is equivalent, maar korter. Als u zich richten op .NET 2.0 U kunt deze syntaxis alleen gebruiken als u de compiler van Visual & NBSP gebruikt; Studio & NBSP; 2008 (of hierboven).

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

Antwoord 2, Autoriteit 102%

Gebruik 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;

Dit zou ook grote flexibiliteit mogelijk maken doordat u de Top 10, 20 10%, enz. Selecteert of als u uw Word Frequency-index gebruikt voor type-ahead, kunt u ook opnemen StartsWithClausule ook.


Antwoord 3, Autoriteit 55%

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

Antwoord 4, Autoriteit 32%

rondkijken, en met behulp van sommige C # 3.0-functies, kunnen we dit doen:

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

Dit is de schoonste manier die ik heb gezien en vergelijkbaar is met de robijnse manier van hanteren van hashes.


Antwoord 5, Autoriteit 31%

U kunt een woordenboek op waarde sorteren en het opslaan op zichzelf (zodat wanneer u erover de waarden in orde komt):

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

Natuurlijk, het is misschien niet correct, maar het werkt.


Antwoord 6, Autoriteit 11%

Op een hoog niveau heb je geen andere keuze dan door het hele woordenboek door te lopen en naar elke waarde te kijken.

Misschien helpt dit:
http://bytes.com/forum/thread563638.html
Kopieer / plakken van 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);
    }
);

Antwoord 7, autoriteit 5%

Je zou toch nooit een woordenboek kunnen sorteren. Ze zijn niet echt besteld. De garanties voor een woordenboek zijn dat de sleutel- en waardeverzamelingen itereerbaar zijn, en waarden kunnen worden opgehaald door index of sleutel, maar er is geen garantie voor een bepaalde volgorde. Daarom zou u het naamwaardepaar in een lijst moeten krijgen.


Antwoord 8, autoriteit 4%

U sorteert geen items in de Dictionary. Woordenboekklasse in .NET is geïmplementeerd als een hashtabel – deze gegevensstructuur is niet per definitie sorteerbaar.

Als u uw verzameling (op sleutel) moet kunnen herhalen, moet u SortedDictionary gebruiken, dat is geïmplementeerd als een binaire zoekboom.

In uw geval is de bronstructuur echter niet relevant, omdat deze is gesorteerd op een ander veld. U moet het nog steeds op frequentie sorteren en in een nieuwe verzameling plaatsen, gesorteerd op het relevante veld (frequentie). Dus in deze verzameling zijn de frequenties sleutels en woorden zijn waarden. Omdat veel woorden dezelfde frequentie kunnen hebben (en je gaat het als sleutel gebruiken), kun je Dictionary noch SortedDictionary gebruiken (ze hebben unieke sleutels nodig). Dit geeft je een SortedList.

Ik begrijp niet waarom u erop staat een link naar het originele item in uw hoofd-/eerste woordenboek te behouden.

Als de objecten in uw collectie een complexere structuur (meer velden) hadden en u nodig had om efficiënt toegang te krijgen tot / sorteren met verschillende velden als sleutels – u zou waarschijnlijk een aangepaste datastructuur nodig hebben die uit de Hoofdopslag die O (1) Insertion and Removal (LinkedList) en Verschillende Indexingstructuren ondersteunt – Woordenboeken / Sorteerden / Sorteerlijsten. Deze indexen zouden een van de velden van uw complexe klasse gebruiken als een sleutel en een aanwijzer / verwijzing naar de LinkedLADNODE in de Linkedlist als een waarde.

U moet inserties en verwijderingen coördineren om uw indexen in synchronisatie te houden met de hoofdinzameling (Linkedlist) en verwijderingen zouden behoorlijk duur zijn, zou ik denken.
Dit is vergelijkbaar met het werk van de database-indexen – ze zijn fantastisch voor lookups, maar ze worden een last wanneer u veel inkomsten en verwijderingen moet uitvoeren.

Al het bovenstaande is alleen gerechtvaardigd als u wat op zoek gaat naar zware verwerking. Als u ze alleen maar eenmaal op de frequentie hoeft uit te voeren, kunt u gewoon een lijst met (anonieme) tuples produceren:

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

Antwoord 9, Autoriteit 3%

Dictionary<string, string> dic= new Dictionary<string, string>();
var ordered = dic.OrderBy(x => x.Value);
return ordered.ToDictionary(t => t.Key, t => t.Value);

Antwoord 10, Autoriteit 2%

Of voor de lol zou u wat LINQ-uitbreidingsniveau kunnen gebruiken:

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

Antwoord 11, autoriteit 2%

Een SortedDictionary-lijst sorteren om te binden aan een ListView-besturingselement met behulp van 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>

Antwoord 12

De andere antwoorden zijn goed, als u alleen een “tijdelijke” lijst wilt hebben, gesorteerd op Waarde. Als u echter een woordenboek wilt hebben dat is gesorteerd op Keydat automatisch synchroniseertmet een ander woordenboek dat is gesorteerd op Value, kunt u de Bijection<K1, K2>klasse.

Bijection<K1, K2>stelt u in staat om de collectie te initialiseren met twee bestaande woordenboeken, dus als u wilt dat een van de woordenboeken ongesorteerd is en u wilt dat de andere wordt gesorteerd, kunt u maak je bijectie met code zoals

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

U kunt dictgebruiken zoals elk normaal woordenboek (het implementeert IDictionary<K, V>), en vervolgens dict.Inverseaanroepen om haal het “inverse” woordenboek op dat is gesorteerd op Value.

Bijection<K1, K2>maakt deel uit van Loyc.Collections.dll, maar als je wilt, kun je gewoon de broncodein uw eigen project.

Opmerking: als er meerdere sleutels zijn met dezelfde waarde, kunt u Bijectionniet gebruiken, maar u kunt handmatig synchroniseren tussen een gewoon Dictionary<Key,Value>en een BMultiMap<Value,Key>.


Antwoord 13

De gemakkelijkste manier om een gesorteerd woordenboek te krijgen, is door de ingebouwde klasse SortedDictionaryte gebruiken:

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

sortedSectionsbevat de gesorteerde versie van sections


Antwoord 14

Eigenlijk hebben woordenboeken in C# geen sort()-methoden.
Aangezien u meer geïnteresseerd bent in sorteren op waarden,
u kunt geen waarden ophalen totdat u ze een sleutel opgeeft.
Kortom, u moet ze doorlopen met behulp van LINQ’s OrderBy(),

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
}

Je kunt één truc doen:

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

of:

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

Het hangt ook af van het soort waarden dat u opslaat: enkelvoudig (zoals string, int) of meervoudig (zoals List, Array, door de gebruiker gedefinieerde klasse).
Als het single is, kun je er een lijst van maken en vervolgens sorteren.
Als het een door de gebruiker gedefinieerde klasse is, dan moet die klasse IComparable, ClassName: IComparable<ClassName>implementeren en compareTo(ClassName c)negeren omdat ze sneller en meer objectgeoriënteerd zijn dan LINQ.


Antwoord 15

Stel dat we een woordenboek hebben 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) U kunt 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);
        }

Antwoord 16

Vereiste naamruimte: using System.Linq;

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

Bestel door desc:

foreach (KeyValuePair<string, int> kvp in counts.OrderByDescending(key => key.Value))
{
// some processing logic for each item if you want.
}

Bestellen op ASC:

foreach (KeyValuePair<string, int> kvp in counts.OrderBy(key => key.Value))
{
// some processing logic for each item if you want.
}

Antwoord 17

Sorteren en afdrukken:

var items = from pair in players_Dic
                orderby pair.Value descending
                select pair;
// Display results.
foreach (KeyValuePair<string, int> pair in items)
{
    Debug.Log(pair.Key + " - " + pair.Value);
}

Wijzig aflopend op acending om de sorteervolgorde te wijzigen


Antwoord 18

U kunt het woordenboek op waarde sorteren en het resultaat in het woordenboek gebruiken met behulp van de onderstaande code:

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

Antwoord 19

Gezien u een woordenboek kunt u deze rechtstreeks op waarden sorteren met onder één voering:

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

Other episodes