2009-08-19 16 views
16

que tienen esta clase:¿Cómo ordenar una lista de objetos por un campo específico en C#?

public class StatInfo 
{ 
    public string contact; 
    public DateTime date; 
    public string action; 
} 

entonces tengo una lista de StatInfo, pero no estoy seguro de cómo clasificar de acuerdo con el campo de fecha. ¿Debo usar el método de clasificación? ¿Debería crear el mío?

var _allStatInfo = new List<StatInfo>(); 
// adding lots of stuff in it 
_allStatInfo.SortByDate??? 

¿Cuál es la mejor manera de hacerlo sin tener que escribir toneladas de código (si es posible)?

Gracias

+0

Espere a que Jon Skeet en aparecer. Su C# en profundidad: lo que necesita para dominar C# 2 y 3 tiene una gran sección sobre eso. – hughdbrown

+0

¡Demasiado tarde! Siempre me sorprende cuando una de mis preguntas sobre C# no obtiene una respuesta de Jon Skeet :) – marcgg

+1

título es incorrecto. dice "matriz" –

Respuesta

48

mediante LINQ:

var sortedList = _allStatInfo.OrderBy(si => si.date).ToList(); 

Clasificación de la lista original:

_allStatInfo.Sort(new Comparison<StatInfo>((x, y) => DateTime.Compare(x.date, y.date))); 
+0

Gracias, el segundo método funcionó. No uso LINQ así que no puedo probar el segundo. – marcgg

3

utilizar una expresión lambda para mapear un par a una comparación:

_allStatInfo.Sort((x, y) => x.date - y.date); 
+0

Gracias por la respuesta, pero me sale un error: No se puede convertir la expresión lambda para escribir System.Collections.Generic.IComparer 'porque no es un tipo de delegado – marcgg

+0

Necesita al menos C# 3.0 (Visual Studio 2008/cualquier edición). –

1

Para un DateTim e no debería haber una necesidad de comparar.

_allStatInfo.OrderyBy(d => d.date); 

o

_allStatInfo.OrderByDescending(d => d.Date); 
+0

Ambos métodos devuelven la lista, por lo que necesitaría _allStatInfo = _allStatInfo.OrderBy (d => d.date) .ToList(); – TruthStands

+0

Gracias, pero una Lista <> no tiene tales funciones si no estoy confundiendo – marcgg

+0

Supongo que esto es LINQ. No estoy usando LINQ – marcgg

3

Para ilustrar la respuesta de Robert C. Cartaino:

public class StatInfo : IComparable<StatInfo> 
{ 
    public string contact; 
    public DateTime date; 
    public string action; 

    public int CompareTo(StatInfo value) 
    { 
     return this.date.CompareTo(value.date); 
    } 
} 

var _allStatInfo = new List<StatInfo>(); 

// this now sorts by date 
_allStatInfo.Sort(); 

No es la solución más general, pero bueno si sólo va a ordenar por fecha. Y, como dijo Robert, aún puede anular siempre la clasificación predeterminada pasando un parámetro IComparer al método de clasificación.

+0

gracias. No se aplica realmente a mi situación ya que solo ordenaré por fecha en esta situación particular, pero lo tendré en cuenta para más adelante – marcgg

+0

@marcgg: El código en mi respuesta hace que la ordenación por fecha sea el comportamiento predeterminado. Entonces, si solo está ordenando por fecha, creo que eso es exactamente lo que quiere. –

11

veo que tienes la respuesta de todos modos, pero ...

  1. puede eliminar causas de la fealdad sólo por la división de la declaración en dos mitades:

    Comparison<StatInfo> comparison = (x, y) => DateTime.Compare(x.date, y.date); 
    _allStatInfo.Sort(comparison); 
    

    Es posible que desee considerar sólo llamar directamente CompareTo, también:

    Comparison<StatInfo> comparison = (x, y) => x.date.CompareTo(y.date); 
    _allStatInfo.Sort(comparison); 
    
  2. puede crear un IComparer<T> implementación usando mi clase ProjectionComparer - es parte de MiscUtil, y he incluido una versión sin comentar en la parte inferior de esta respuesta. A continuación, escribiría:

    _allStatInfo.Sort(ProjectionComparer<StatInfo>.Create(x => x.date)); 
    
  3. Incluso si usted está utilizando .NET 2.0, todavía se puede utilizar LINQ a través de LINQBridge.

Aquí está la clase ProjectionComparer requerida para la segunda respuesta. Las primeras dos clases son realmente solo ayudantes para que la inferencia de tipo genérico funcione mejor.

public static class ProjectionComparer 
{ 
    public static ProjectionComparer<TSource, TKey> Create<TSource, TKey> 
     (Func<TSource, TKey> projection) 
    { 
     return new ProjectionComparer<TSource, TKey>(projection); 
    } 

    public static ProjectionComparer<TSource, TKey> Create<TSource, TKey> 
     (TSource ignored, Func<TSource, TKey> projection) 
    { 
     return new ProjectionComparer<TSource, TKey>(projection); 
    } 

} 

public static class ProjectionComparer<TSource> 
{ 
    public static ProjectionComparer<TSource, TKey> Create<TKey> 
     (Func<TSource, TKey> projection) 
    { 
     return new ProjectionComparer<TSource, TKey>(projection); 
    } 
} 

public class ProjectionComparer<TSource, TKey> : IComparer<TSource> 
{ 
    readonly Func<TSource, TKey> projection; 
    readonly IComparer<TKey> comparer; 

    public ProjectionComparer(Func<TSource, TKey> projection) 
     : this (projection, null) 
    { 
    } 

    public ProjectionComparer(Func<TSource, TKey> projection, 
           IComparer<TKey> comparer) 
    { 
     projection.ThrowIfNull("projection"); 
     this.comparer = comparer ?? Comparer<TKey>.Default; 
     this.projection = projection; 
    } 

    public int Compare(TSource x, TSource y) 
    { 
     // Don't want to project from nullity 
     if (x==null && y==null) 
     { 
      return 0; 
     } 
     if (x==null) 
     { 
      return -1; 
     } 
     if (y==null) 
     { 
      return 1; 
     } 
     return comparer.Compare(projection(x), projection(y)); 
    } 
} 
+1

¿Estás diciendo que mi código es feo? :-( –

+0

Oh, gracias, justo cuando estaba diciendo que no obtuve una respuesta tuya sobre una pregunta de C# :) Mantendré la respuesta de Ben aceptada pero la voté como tuya y estoy seguro de que estará justo debajo de – marcgg

+1

@Ben: Simplemente no me gustan esos corchetes si puedo evitarlo :) –

1

que trabajó para mí ُSorting array of custom type using delegate

// sort array by name 
Array.Sort(users, delegate(User user1, User user2) 
      { 
      return user1.Name.CompareTo(user2.Name); 
      }); 
// write array (output: Betty23 Lisa25 Susan20) 
foreach (User user in users) Console.Write(user.Name + user.Age + " "); 
+0

Gracias, única respuesta que funcionó para mí. – lama12345

Cuestiones relacionadas