C#:如何根据字符串列表对对象列表进行排序

时间:2012-03-09 11:38:18

标签: c# linq sorting collections lambda

我有两个列表,如

 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_lstStudentsl_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

  3. 请以简单的方式帮助我(Linq或Lambda)

7 个答案:

答案 0 :(得分:9)

试试这个:

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

我认为这很清楚地表达了意图。

答案 1 :(得分:2)

怎么样

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

答案 2 :(得分: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]));

答案 3 :(得分: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" }, 
                        };

答案 4 :(得分: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();

答案 5 :(得分:1)

尝试使用以下代码:

 l_lstStudents = (from name in l_lstNames
                  join student in l_lstStudents
                  on name equals student.Name
                  select student).ToList<Test>();

答案 6 :(得分:1)

var newList = l_lstNames.Join(l_lstStudents, 
    s => s, 
    test => test.Name, 
    (s, test) => new Test { Name = s, Age = test.Age }
    ).ToList();