ordenar alfabeticamente c#
C#List<> Ordenar por x luego y (6)
Similar a List <> OrderBy Alphabetical Order , queremos ordenar por un elemento, luego otro. queremos lograr el equivalente funcional de
SELECT * from Table ORDER BY x, y
Tenemos una clase que contiene una serie de funciones de clasificación, y no tenemos problemas clasificando por un elemento.
Por ejemplo:
public class MyClass {
public int x;
public int y;
}
List<MyClass> MyList;
public void SortList() {
MyList.Sort( MySortingFunction );
}
Y tenemos lo siguiente en la lista:
Unsorted Sorted(x) Desired
--------- --------- ---------
ID x y ID x y ID x y
[0] 0 1 [2] 0 2 [0] 0 1
[1] 1 1 [0] 0 1 [2] 0 2
[2] 0 2 [1] 1 1 [1] 1 1
[3] 1 2 [3] 1 2 [3] 1 2
La clasificación estable sería preferible, pero no obligatoria. La solución que funciona para .Net 2.0 es bienvenida.
El truco es implementar un tipo estable. Creé una clase de widget que puede contener tus datos de prueba:
public class Widget : IComparable
{
int x;
int y;
public int X
{
get { return x; }
set { x = value; }
}
public int Y
{
get { return y; }
set { y = value; }
}
public Widget(int argx, int argy)
{
x = argx;
y = argy;
}
public int CompareTo(object obj)
{
int result = 1;
if (obj != null && obj is Widget)
{
Widget w = obj as Widget;
result = this.X.CompareTo(w.X);
}
return result;
}
static public int Compare(Widget x, Widget y)
{
int result = 1;
if (x != null && y != null)
{
result = x.CompareTo(y);
}
return result;
}
}
Implementé IComparable, por lo que puede ser ordenado de manera inestable por List.Sort ().
Sin embargo, también implementé el método estático Compare, que se puede pasar como un delegado a un método de búsqueda.
Tomé prestado este método de clasificación de inserción de C # 411 :
public static void InsertionSort<T>(IList<T> list, Comparison<T> comparison)
{
int count = list.Count;
for (int j = 1; j < count; j++)
{
T key = list[j];
int i = j - 1;
for (; i >= 0 && comparison(list[i], key) > 0; i--)
{
list[i + 1] = list[i];
}
list[i + 1] = key;
}
}
Pondrá esto en la clase de clase de ayudantes que mencionó en su pregunta.
Ahora, para usarlo:
static void Main(string[] args)
{
List<Widget> widgets = new List<Widget>();
widgets.Add(new Widget(0, 1));
widgets.Add(new Widget(1, 1));
widgets.Add(new Widget(0, 2));
widgets.Add(new Widget(1, 2));
InsertionSort<Widget>(widgets, Widget.Compare);
foreach (Widget w in widgets)
{
Console.WriteLine(w.X + ":" + w.Y);
}
}
Y produce:
0:1
0:2
1:1
1:2
Press any key to continue . . .
Esto probablemente podría limpiarse con algunos delegados anónimos, pero lo dejaré en tus manos.
EDITAR : Y NoBugz demuestra el poder de los métodos anónimos ... así que, considera el mío más oldschool: P
Esto puede ayudarlo, Cómo ordenar la lista genérica de C #
Para versiones de .Net donde puede usar LINQ OrderBy
y ThenBy
(o ThenByDescending
si es necesario):
using System.Linq;
....
List<SomeClass>() a;
List<SomeClass> b = a.OrderBy(x => x.x).ThenBy(x => x.y).ToList();
Nota: para .Net 2.0 (o si no puede usar LINQ), vea la respuesta de Hans Passant a esta pregunta.
Tenga en cuenta que no necesita una clasificación estable si compara todos los miembros. La solución 2.0, como se solicita, puede verse así:
public void SortList() {
MyList.Sort(delegate(MyClass a, MyClass b)
{
int xdiff = a.x.CompareTo(b.x);
if (xdiff != 0) return xdiff;
else return a.y.CompareTo(b.y);
});
}
Tenga en cuenta que esta solución 2.0 sigue siendo preferible a la popular solución 3.5 Linq, realiza un ordenamiento in situ y no tiene el requisito de almacenamiento O (n) del enfoque de Linq. A menos que prefiera que el objeto List original permanezca intacto, por supuesto.
Tuve un problema donde OrderBy y ThenBy no me dieron el resultado deseado (o simplemente no sabía cómo usarlos correctamente).
Fui con una lista. Solucione algo como esto.
var data = (from o in database.Orders Where o.ClientId.Equals(clientId) select new {
OrderId = o.id,
OrderDate = o.orderDate,
OrderBoolean = (SomeClass.SomeFunction(o.orderBoolean) ? 1 : 0)
});
data.Sort((o1, o2) => (o2.OrderBoolean.CompareTo(o1.OrderBoolean) != 0
o2.OrderBoolean.CompareTo(o1.OrderBoolean) : o1.OrderDate.Value.CompareTo(o2.OrderDate.Value)));
IComparer implementar la interfaz IComparer . Aquí hay una buena publicación con código de ejemplo.