development

값별로 사전을 정렬하는 방법은 무엇입니까?

big-blog 2020. 9. 29. 08:05
반응형

값별로 사전을 정렬하는 방법은 무엇입니까?


저는 종종 키와 값으로 구성된 사전을 값별로 정렬해야합니다. 예를 들어, 주파수별로 정렬하려는 단어와 각 주파수의 해시가 있습니다.

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

.NET 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 % 등을 선택할 수 있다는 점에서 큰 유연성을 허용합니다. 또는에 대해 단어 빈도 색인을 사용하는 경우 절도 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
}

이것은 내가 본 것 중 가장 깨끗한 방법이며 해시를 처리하는 Ruby 방법과 유사합니다.


값을 기준으로 사전을 정렬하고 다시 저장할 수 있습니다 (각각을 검색 할 때 값이 순서대로 나오도록).

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

물론 정확하지 않을 수도 있지만 작동합니다.


높은 수준에서 전체 사전을 살펴보고 각 값을 살펴볼 다른 선택의 여지가 없습니다.

아마도 이것이 도움이 될 것입니다 : http://bytes.com/forum/thread563638.html 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);
    }
);

You'd never be able to sort a dictionary anyway. They are not actually ordered. The guarantees for a dictionary are that the key and value collections are iterable, and values can be retrieved by index or key, but there is no guarantee of any particular order. Hence you would need to get the name value pair into a list.


You do not sort entries in the Dictionary. Dictionary class in .NET is implemented as a hashtable - this data structure is not sortable by definition.

If you need to be able to iterate over your collection (by key) - you need to use SortedDictionary, which is implemented as a Binary Search Tree.

In your case, however the source structure is irrelevant, because it is sorted by a different field. You would still need to sort it by frequency and put it in a new collection sorted by the relevant field (frequency). So in this collection the frequencies are keys and words are values. Since many words can have the same frequency (and you are going to use it as a key) you cannot use neither Dictionary nor SortedDictionary (they require unique keys). This leaves you with a SortedList.

I don't understand why you insist on maintaining a link to the original item in your main/first dictionary.

If the objects in your collection had a more complex structure (more fields) and you needed to be able to efficiently access/sort them using several different fields as keys - You would probably need a custom data structure that would consist of the main storage that supports O(1) insertion and removal (LinkedList) and several indexing structures - Dictionaries/SortedDictionaries/SortedLists. These indexes would use one of the fields from your complex class as a key and a pointer/reference to the LinkedListNode in the LinkedList as a value.

You would need to coordinate insertions and removals to keep your indexes in sync with the main collection (LinkedList) and removals would be pretty expensive I'd think. This is similar to how database indexes work - they are fantastic for lookups but they become a burden when you need to perform many insetions and deletions.

All of the above is only justified if you are going to do some look-up heavy processing. If you only need to output them once sorted by frequency then you could just produce a list of (anonymous) tuples:

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

Or for fun you could use some LINQ extension goodness:

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

Sort values

This show how to sort the values in a Dictionary. We see a console program you can compile in Visual Studio and run. It adds keys to a Dictionary and then sorts them by their values. Remember that Dictionary instances are not initially sorted in any way. We use the LINQ orderby keyword in a query statement.

OrderBy Clause Program that sorts Dictionary [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;
    }
}

Output

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

Sorting a SortedDictionary list to bind into a ListView control using 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>

The easiest way to get a sorted Dictionary is to use the built in SortedDictionary class:

//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 contains the sorted version of sections


The other answers are good, if all you want is to have a "temporary" list sorted by Value. However, if you want to have a dictionary sorted by Key that automatically synchronizes with another dictionary that is sorted by Value, you could use the Bijection<K1, K2> class.

Bijection<K1, K2> allows you to initialize the collection with two existing dictionaries, so if you want one of them to be unsorted, and you want the other one to be sorted, you could create your bijection with code like

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

You can use dict like any normal dictionary (it implements IDictionary<K, V>), and then call dict.Inverse to get the "inverse" dictionary which is sorted by Value.

Bijection<K1, K2> is part of Loyc.Collections.dll, but if you want, you could simply copy the source code into your own project.

Note: In case there are multiple keys with the same value, you can't use Bijection, but you could manually synchronize between an ordinary Dictionary<Key,Value> and a BMultiMap<Value,Key>.


Suppose we have a dictionary as

   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) you can use 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);
        }

Actually in C#, Dictionaries dint have sort() methods, as you are more interested in sort by values, you cant get values until you provide them key, in short, you need to iterate through them, using LINQ's Order By,

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
}

you can do one trick,

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

or

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

its also depend on what kind of values you are storing,
is it single (like string, int) or multiple (like List, Array, user defined class),
if single you can make list of it then apply sort.
if user defined class, then that class must implement IComparable,
ClassName: IComparable<ClassName> and override compareTo(ClassName c) as they are more faster than LINQ, and more object oriented.


You can sort the Dictionary by value and get the result in dictionary using the code below:

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

Given you have a dictionary you can sort them directly on values using below one liner:

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

참고URL : https://stackoverflow.com/questions/289/how-do-you-sort-a-dictionary-by-value

반응형