2012-03-09 16 views
9

estoy teniendo dos lista comoC#: ¿Cómo ordenar una lista de objetos basado en una lista de cadena

List<String> l_lstNames = new List<String> { "A1", "A3", "A2", "A4", "A0" }; 

List<Test> l_lstStudents = new List<Test> 
          { new Test { Age = 20, Name = "A0" }, 
           new Test { Age = 21, Name = "A1" }, 
           new Test { Age = 22, Name = "A2" }, 
           new Test { Age = 23, Name = "A3" }, 
           new Test { Age = 24, Name = "A4" }, 
          }; 

Dónde Test es clase como

public class Test 
    { 
     public String Name; 
     public Int32 Age; 
    } 

necesito para ordenar los elementos en el l_lstStudents basado en el l_lstNames. Por lo que la lista ordenada será como,

List<Test> l_lstStudents = new List<Test> 
         { new Test { Age = 21, Name = "A1" }, 
          new Test { Age = 23, Name = "A3" }, 
          new Test { Age = 22, Name = "A2" }, 
          new Test { Age = 24, Name = "A4" }, 
          new Test { Age = 20, Name = "A0" }, 
         }; 

Ahora estoy usando for para hacer esto.

Como

  1. Crear una nueva lista de objetos Test.

  2. Iterate el ciclo l_lstNames y busca el objeto Test de l_lstStudent y agrégalo a la lista recién creada. Finalmente asignar la nueva lista de l_lstStudent

Por favor, ayúdame a hacer esto de una manera sencilla (LINQ o lambda)

+0

Sé que dijo sencillo, pero ¿estás más preocupado por el rendimiento o pocas líneas de código? – Tung

+0

posible duplicado de [Lista de clasificación C# basada en otra lista] (http://stackoverflow.com/questions/3355928/c-sharp-sort-list-based-on-another-list) – nawfal

Respuesta

9

Prueba esto:

l_lstStudents = l_lstStudents.OrderBy(s => l_lstNames.IndexOf(s.Name)).ToList() 

Creo que expresa la intención bastante claramente.

1

Pruebe algo como:

List<String> l_lstNames = new List<String> { "A1", "A3", "A2", "A4", "A0" }; 

List<Test> l_lstStudents = new List<Test> 
          { new Test { Age = 20, Name = "A0" }, 
           new Test { Age = 21, Name = "A1" }, 
           new Test { Age = 22, Name = "A2" }, 
           new Test { Age = 23, Name = "A3" }, 
           new Test { Age = 24, Name = "A4" }, 
          }; 

// We transform the list in a dictionary to make it faster to access. 
// The first Select creates a new object with the index of the name and 
// the ToDictionary creates the Dictionary. 
// Note that technically on a small list (like 5 elements) 
// it's probably faster to IndexOf directly the List... 
// This is the problem of premature optimization :-) :-) 
// If you know the list will always be 5 elements then probably 
// IndexOf is more than enough. 
var dict = l_lstNames.Select((p, i) => new { Index = i, Name = p }) 
        .ToDictionary(p => p.Name, p => p.Index); 

// We sort it. This works because 3 < 5 => 3 - 5 < 0, 5 > 3 => 5 - 3 > 0, 5 == 5 => 5 - 5 == 0 
l_lstStudents.Sort((p, q) => dict[p.Name] - dict[q.Name]); 

// We could do something like and it would be clearer. 
l_lstStudents.Sort((p, q) => dict[p.Name].CompareTo(dict[q.Name])); 
2

¿Qué tal

var studentLookup = l_lstStudents.ToDictionary(s => s.Name, s => s); 
return l_lstNames.Select(n => studentLookup[n]); 
1

Usando

l_lstStudents = l_lstStudents.OrderBy(x => l_lstNames.IndexOf(x.Name)).ToList(); 

en un programa de ensayos a pequeña

public class Test 
{ 
    public String Name; 
    public Int32 Age; 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     List<String> l_lstNames = new List<String> { "A1", "A3", "A2", "A4", "A0" }; 

     List<Test> l_lstStudents = new List<Test> 
            { new Test { Age = 20, Name = "A0" }, 
             new Test { Age = 21, Name = "A1" }, 
             new Test { Age = 22, Name = "A2" }, 
             new Test { Age = 23, Name = "A3" }, 
             new Test { Age = 24, Name = "A4" }, 
            }; 

     l_lstStudents = l_lstStudents.OrderBy(x => l_lstNames.IndexOf(x.Name)).ToList(); 
    } 
} 

resultados en

Age  21  int 
Name "A1" string 

Age  23  int 
Name "A3" string 

Age  22  int 
Name "A2" string 

Age  24  int 
Name "A4" string 

Age  20  int 
Name "A0" string 

y por lo tanto es:

List<Test> l_lstStudents = new List<Test> 
         { new Test { Age = 21, Name = "A1" }, 
          new Test { Age = 23, Name = "A3" }, 
          new Test { Age = 22, Name = "A2" }, 
          new Test { Age = 24, Name = "A4" }, 
          new Test { Age = 20, Name = "A0" }, 
         }; 
1

probar esto. Ponerlo en un diccionario puede ahorrar algo de consultar el tiempo:

int i = 0; 
Dictionary<string, int> ordinalValues = l_lstNames.ToDictionary(name => name, name => i++); 
var sortedStudents = l_lstStudents.OrderBy(a => ordinalValues[a.Name]).ToList(); 
1

Pruebe con siguiente código:

l_lstStudents = (from name in l_lstNames 
        join student in l_lstStudents 
        on name equals student.Name 
        select student).ToList<Test>(); 
1
var newList = l_lstNames.Join(l_lstStudents, 
    s => s, 
    test => test.Name, 
    (s, test) => new Test { Name = s, Age = test.Age } 
    ).ToList(); 
Cuestiones relacionadas