2012-03-09 2 views
9

Я имею два списка, какC#: Как отсортировать список объектов, на основе списка строки

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" }, 
          }; 

Где Test Классно как

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

Мне нужно отсортировать элементы в l_lstStudents на основе l_lstNames. Таким образом, отсортированный список будет походить,

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" }, 
         }; 

Теперь я использую for, чтобы сделать это.

Как

  1. Создать новый список Test объектов.

  2. Итереть цикл для l_lstNames и извлечь объект Test из l_lstStudent и добавить его во вновь созданный список. Наконец назначить новый список l_lstStudent

Пожалуйста, помогите мне сделать это простым способом (Linq или лямбда)

+0

Я знаю, что ты сказал просто, но вы больше озабочены производительности или несколько строк кода? – Tung

+0

Возможный дубликат [Сортировка списка C# на основе другого списка] (http://stackoverflow.com/questions/3355928/c-sharp-sort-list-based-on-another-list) – nawfal

ответ

9

Попробуйте это:

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

Я думаю, что выражает намерение вполне ясно.

1

Попробуйте что-то вроде:

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

Как насчет

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

Использование

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

в небольшой тестовой программы

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

приводит

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 

и, таким образом, является:

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

Попробуйте это. Собираем в словаре может сэкономить посмотреть на время:

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

Попробуйте с помощью следующего кода:

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(); 
Смежные вопросы