C #: Как отсортировать список объектов на основе списка строк - PullRequest
9 голосов
/ 09 марта 2012

У меня есть два списка, как

 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 или Lambda)

Ответы [ 7 ]

9 голосов
/ 09 марта 2012

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

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

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

2 голосов
/ 09 марта 2012

Как насчет

var studentLookup = l_lstStudents.ToDictionary(s => s.Name, s => s);
return l_lstNames.Select(n => studentLookup[n]);
1 голос
/ 09 марта 2012
var newList = l_lstNames.Join(l_lstStudents, 
    s => s, 
    test => test.Name, 
    (s, test) => new Test { Name = s, Age = test.Age }
    ).ToList();
1 голос
/ 09 марта 2012

Попробуйте использовать следующий код:

 l_lstStudents = (from name in l_lstNames
                  join student in l_lstStudents
                  on name equals student.Name
                  select student).ToList<Test>();
1 голос
/ 09 марта 2012

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

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 голос
/ 09 марта 2012

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

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 голос
/ 09 марта 2012

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

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]));
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...