在不使用foreach的情况下在List中查找对象

时间:2012-03-16 08:05:24

标签: c# .net

我有以下班级学生的名单

class student
{
   Guid id;
   string name;
}

该列表包含多名学生。要搜索具有特定ID的学生,我需要使用foreach循环并比较每个学生的ID。

我正在寻找一个更好的替代品而不是foreach循环。有没有其他选择?

[编辑]:我认为更好的选择是在执行时间和性能方面优化的解决方案

[EDIT2] 还有一个问题,如果id是Guid会怎么样。

谢谢,

拉​​姆

6 个答案:

答案 0 :(得分:6)

如果每个student只能在列表中显示一次,则可能需要使用Dictionary<int, stutent>。然后,您将有一种非常有效的方式通过id查找学生。

Dictionary<int, student> students = GetSomeStudents();

// locate student with id = 42
if (students.ContainsKey(42))
{
    var student = students[42];
    // do something useful
}

答案 1 :(得分:5)

没有什么能真正改变你必须遍历列表的事实。但你可以使用LINQ:

List<Student> studentsList = ReadStudentsList();
var student = studentsList.Where(s => s.id == ID_IM_LOOKING_FOR).Single();

根据@FredrikMörk的回答,这可以缩短为:

var student = studentsList.Single(s => s.id == ID_IM_LOOKING_FOR);

另请注意,如果找不到学生,Single()将抛出异常。如果您只想返回null,请使用SingleOrDefault()

实际想要做的是将学生存放在地图中:

Dictionary<int, Student> students = ReadStudentsMap();
var student = students[ID_IM_LOOKING_FOR];

这有一个方式更好的性能(对于哈希表来说是O(1),对于树来说是O(log(n)))而不是查看列表(O(n))!

答案 2 :(得分:2)

您可以使用LINQ:

var student = students.SingleOrDefault(s => s.id == 12);

Enumerable.SingleOrDefault Method

答案 3 :(得分:1)

如果您不想使用foreach lop,LINQ是可选项,因此您的代码将如下所示

var student = studentsList.FirstOrDefault(s => s.id == ID_IM_LOOKING_FOR);

答案 4 :(得分:0)

这是一个想法,以避免迭代列表:

  • 按Student.Id
  • 对列表进行排序
  • 实施更复杂的搜索算法(例如二进制搜索binary search

答案 5 :(得分:0)

您可以使用任何使用哈希查找的集合,因为它们的成员查找速度非常快。例如Dictionary <K,V>OrderedDictionary。还存在非泛型Hashtable,其通常由通用Dictionary<K,V>呈现为冗余。在Big-O表示法中,这些集合的按键检索的元素检索时间为O(1),这是最好的。

要访问元素,不要使用ContainsKey,而不是使用TryGetValue,您可以使用Dictionary<Guid, Student> students = GetStudents(); Student student; if (students.TryGetValue(guid, out student)) { // found } 方法,例如:

OrderedDictionary

BTW,{{1}}还允许您按索引访问元素。