Estoy escribiendo un programa para establecer una secuencia en la que aparecerán varios objetos en el informe. La secuencia es la posición Y (celda) en la hoja de cálculo de Excel.
A continuación se muestra una parte de demostración del código. Lo que quiero lograr es tener una colección, lo que me permitirá agregar varios objetos y puedo obtener una colección ordenada según la secuencia
SortedList list = new SortedList();
Header h = new Header();
h.XPos = 1;
h.name = "Header_1";
list.Add(h.XPos, h);
h = new Header();
h.XPos = 1;
h.name = "Header_2";
list.Add(h.XPos, h);
Sé que SortedList
no lo permitirán y he estado buscando una alternativa. No quiero eliminar los duplicados y ya lo intenté List<KeyValuePair<int, object>>
.
Gracias.
c#
.net
linq
collections
sortedlist
Mayur Kotlikar
fuente
fuente
List
?Respuestas:
¡Utilice su propio IComparer!
Como ya se indicó en algunas otras respuestas, debe usar su propia clase de comparación. Por este motivo, uso una clase IComparer genérica, que funciona con cualquier cosa que implemente IComparable:
Lo usará cuando instale un nuevo SortedList, SortedDictionary, etc.
Aquí int es la clave que se puede duplicar.
fuente
SortedDictionary
. También permite la eliminación.Puede utilizar List <> de forma segura. La Lista tiene un método Sort, una sobrecarga del cual acepta IComparer. Puede crear su propia clase clasificadora como. He aquí un ejemplo:
fuente
Yo uso lo siguiente:
Mi caso de prueba:
La salida:
fuente
El problema es que el diseño de la estructura de datos no coincide con los requisitos: es necesario almacenar varios encabezados para los mismos XPos. Por lo tanto,
SortedList<XPos, value>
no debería tener un valor deHeader
, sino un valor deList<Header>
. Es un cambio simple y pequeño, pero resuelve todos los problemas y evita la creación de nuevos problemas como otras soluciones sugeridas (ver explicación a continuación):Tenga en cuenta que agregar una clave "divertida", como agregar un número aleatorio o pretender que 2 XPos con el mismo valor son diferentes conduce a muchos otros problemas. Por ejemplo, resulta difícil o incluso imposible eliminar un encabezado en particular.
También tenga en cuenta que el rendimiento de clasificación es mucho mejor si solo
List<Header>
se deben clasificar unos pocos que todosHeader
. Ejemplo: si hay 100 XPos y cada uno tiene 100 encabezados, esHeader
necesario ordenar 10000 en lugar de 100List<Header>
.Por supuesto, esta solución también tiene una desventaja: si hay muchos XPos con solo 1 encabezado, se deben crear tantas listas, lo que supone una sobrecarga.
fuente
Solución más simple (en comparación con todas las anteriores): use
SortedSet<T>
, acepta unaIComparer<SortableKey>
clase, luego implemente el método Compare de esta manera:fuente
Muchas gracias por tu ayuda. Mientras buscaba más, encontré esta solución. (Disponible en Stackoverflow.com en otra pregunta)
Primero, creé una clase que encapsularía mis objetos para clases (encabezados, pie de página, etc.)
Entonces, se supone que esta clase se mantiene en los objetos, y PosX de cada objeto va como int Position
Lo que finalmente obtengo es la lista ordenada de "Secuencia".
fuente
¿Intentó
Lookup<TKey, TElement>
que permita claves duplicadas http://msdn.microsoft.com/en-us/library/bb460184.aspxfuente
Lookup
creo que no hay ningún constructor público . ¿Alguna buena forma de evitar esto?ToLookup
en cualquieraIEnumerable<T>
.Puede usar SortedList, usar su valor para TKey e int (count) para TValue.
Aquí tienes un ejemplo: una función que ordena las letras de una palabra.
fuente
Esta clase de colección mantendrá duplicados e insertará el orden de clasificación para el duplicado. El truco consiste en etiquetar los elementos con un valor único a medida que se insertan para mantener un orden de clasificación estable. Luego lo envolvemos todo en una interfaz ICollection.
una clase de prueba
La estructura de etiquetado
El ayudante del comparador lambda
fuente
El problema es que usas algo como clave que no es una clave (porque ocurre varias veces).
Entonces, si tiene coordenadas reales, tal vez debería tomar
Point
como clave para su SortedList.O crea un
List<List<Header>>
donde su primer índice de lista define la posición xy la lista interna indexa la posición y (o viceversa si lo desea).fuente
La clave (juego de palabras intencionado) para esto es crear una
IComparable
clase basada en que mantenga la igualdad y el hash, pero nunca se compare con 0 si no es igual. Esto se puede hacer y se puede crear con un par de bonificaciones: clasificación estable (es decir, los valores agregados a la lista ordenada primero mantendrán su posición) yToString()
simplemente puede devolver el valor real de la cadena de claves.Aquí hay una clave de estructura que debería funcionar:
fuente
Linq.Lookup es genial y todo, pero si su objetivo es simplemente recorrer las "claves" mientras permite que se dupliquen, puede usar esta estructura:
Entonces puedes escribir:
HTH
fuente
El truco consiste en aumentar tu objeto con una clave única. Vea la siguiente prueba que pasa. Quiero mantener mis puntos ordenados por su valor X. El solo uso de un Point2D desnudo en mi función de comparación hará que se eliminen los puntos con el mismo valor X. Así que envuelvo el Point2D en una clase de etiquetado llamada Indexado.
Las utilidades para hacer que esto funcione son
Un comparador que lleva una lambda
Una estructura de etiquetado
fuente
Así es como resolví el problema. Está destinado a ser seguro para subprocesos, aunque simplemente puede eliminar la
lock
s si no lo necesita. También tengaInsert
en cuenta que no se admite arbitrario en un índice porque eso podría violar la condición de clasificación.fuente
Crea una clase y consulta la lista:
fuente
Esta es mi opinión sobre esto. Tenga en cuenta que aquí puede haber dragones, C # todavía es bastante nuevo para mí.
Uso:
fuente
Queue
en BCL, que representa una colección de elementos de primero en entrar, primero en salir. La semántica de tu clase es diferente. Su clase tiene un comienzo (donde los elementos se eliminan de la cola) pero no un final (un elemento se puede insertar en cualquier lugar). Entonces, elEnqueue
método en su clase no tiene sentido en mi humilde opinión.PriorityQueue
sería un nombre más apropiado.-2 * 5 == +10
), por lo que no es un gran problema. :-)