valor recorrer por ordenar las ejemplo dict diccionario como claves buscar c# .net sorting dictionary

c# - recorrer - ¿Cómo ordenas un diccionario por valor?



ordenar un diccionario python por valor (18)

A menudo tengo que ordenar un diccionario, que consiste en claves y valores, por valor. Por ejemplo, tengo un hash de palabras y frecuencias respectivas, que quiero ordenar por frecuencia.

Hay una lista SortedList que es buena para un solo valor (por ejemplo, frecuencia), que quiero mapear de nuevo a la palabra.

SortedDictionary orden por clave, no valor. Algunos recurren a una clase personalizada , pero ¿hay una forma más limpia?


Dado que tiene un diccionario, puede clasificarlos directamente en valores utilizando el siguiente forro:

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


De todos modos, nunca podrías ordenar un diccionario. En realidad no están ordenados. Las garantías para un diccionario son que la clave y las colecciones de valores son iterables, y los valores se pueden recuperar por índice o clave, pero no hay garantía de ningún orden en particular. Por lo tanto, necesitarías obtener el par de valores de nombre en una lista.


En realidad, en C #, los diccionarios no tienen métodos sort (), ya que está más interesado en ordenar por valores, no puede obtener valores hasta que les proporcione la clave, en resumen, debe recorrerlos, utilizando el orden de LINQ de,

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 }

puedes hacer un truco,

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

o

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

También depende de qué tipo de valores está almacenando,
es simple (como cadena, int) o múltiple (como Lista, Array, clase definida por el usuario),
Si está solo puede hacer una lista de la misma y luego aplicar orden.
Si la clase definida por el usuario, entonces esa clase debe implementar IComparable,
ClassName: IComparable<ClassName> y reemplaza compareTo(ClassName c) ya que son más rápidos que LINQ y más orientados a objetos.


En un nivel alto, no tiene otra opción que recorrer todo el Diccionario y observar cada valor.

Tal vez esto ayude: http://bytes.com/forum/thread563638.html Copiar / pegar de 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); } );


La forma más fácil de obtener un diccionario ordenado es usar la clase 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 contendrá la versión ordenada de las sections


Las otras respuestas son buenas, si lo único que desea es tener una lista "temporal" ordenada por Valor. Sin embargo, si desea tener un diccionario ordenado por Key que se sincronice automáticamente con otro diccionario ordenado por Value , puede usar la Bijection<K1, K2> .

Bijection<K1, K2> permite inicializar la colección con dos diccionarios existentes, por lo que si desea que uno de ellos no esté clasificado, y desea que el otro se ordene, puede crear su bijection con un código como

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

Puede usar dict como cualquier diccionario normal (implementa IDictionary<K, V> ), y luego llamar a dict.Inverse para obtener el diccionario "inverso" que está ordenado por Value .

Bijection<K1, K2> es parte de Loyc.Collections.dll , pero si lo desea, simplemente puede copiar el código fuente en su propio proyecto.

Nota : En caso de que haya varias claves con el mismo valor, no puede usar Bijection , pero puede sincronizar manualmente entre un Dictionary<Key,Value> ordinario Dictionary<Key,Value> y un BMultiMap<Value,Key> .


Mirando a nuestro alrededor, y usando algunas características de C # 3.0 podemos hacer esto:

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

Esta es la forma más limpia que he visto y es similar a la forma en que Ruby maneja los hashes.


O por diversión puedes usar algo de bondad de extensión 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));


Ordenar una lista SortedDictionary para enlazar en un control ListView usando 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>


Puede ordenar el Diccionario por valor y obtener el resultado en el diccionario utilizando el siguiente código:

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


Puede ordenar un Diccionario por valor y guardarlo de nuevo en sí mismo (de modo que cuando se encuentre sobre él, los valores salgan en orden):

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

Claro, puede que no sea correcto, pero funciona.


Supongamos que tenemos un diccionario como

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


Usted no ordena las entradas en el Diccionario. La clase de diccionario en .NET se implementa como una tabla hash: esta estructura de datos no se puede clasificar por definición.

Si necesita poder iterar sobre su colección (por clave), debe usar SortedDictionary, que se implementa como un árbol de búsqueda binario.

En su caso, sin embargo, la estructura de origen es irrelevante, ya que está ordenada por un campo diferente. Todavía necesitaría clasificarlo por frecuencia y colocarlo en una nueva colección ordenada por el campo relevante (frecuencia). Así que en esta colección las frecuencias son claves y las palabras son valores. Como muchas palabras pueden tener la misma frecuencia (y la usarás como una clave), no puedes usar ni Dictionary ni SortedDictionary (requieren claves únicas). Esto te deja con una lista ordenada.

No entiendo por qué insiste en mantener un enlace al artículo original en su diccionario principal / primero.

Si los objetos en su colección tuvieran una estructura más compleja (más campos) y usted necesitara poder accederlos / ordenarlos de manera eficiente utilizando varios campos diferentes como claves: probablemente necesitaría una estructura de datos personalizada que consistiría en el almacenamiento principal que admite la inserción y eliminación de O (1) (LinkedList) y varias estructuras de indexación - Dictionaries / SortedDictionaries / SortedLists. Estos índices usarían uno de los campos de su clase compleja como clave y un puntero / referencia al LinkedListNode en el LinkedList como un valor.

Necesitaría coordinar inserciones y eliminaciones para mantener sus índices sincronizados con la colección principal (LinkedList) y las eliminaciones serían bastante caras, me parece. Esto es similar a cómo funcionan los índices de la base de datos: son fantásticos para las búsquedas, pero se convierten en una carga cuando necesita realizar muchas inserciones y eliminaciones.

Todo lo anterior solo se justifica si va a realizar un procesamiento pesado de búsqueda. Si solo necesita enviarlos una vez ordenados por frecuencia, solo puede generar una lista de tuplas (anónimas):

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


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

Esto también permitiría una gran flexibilidad en cuanto a que puede seleccionar los 10, 20, 10%, etc. superiores. O si está utilizando su índice de frecuencia de palabras para la StartsWith type-ahead , también podría incluir la cláusula StartsWith .


Utilizar:

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

Ya que está apuntando a .NET 2.0 o superior, puede simplificar esto en la sintaxis lambda: es equivalente, pero más breve. Si está apuntando a .NET 2.0, solo puede usar esta sintaxis si está usando el compilador de Visual Studio 2008 (o superior).

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


Valores de clasificación

Esto muestra cómo ordenar los valores en un Diccionario. Vemos un programa de consola que puede compilar en Visual Studio y ejecutar. Agrega claves a un Diccionario y luego las ordena por sus valores. Recuerde que las instancias del Diccionario no están inicialmente ordenadas de ninguna manera. Usamos la palabra clave orderby LINQ en una declaración de consulta.

OrderBy Cláusula programa que ordena Diccionario [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; } }

Salida

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


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


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