简体   繁体   English

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

[英]Finding object in List without using foreach

I have list of following class Student 我有以下班级学生名单

class student
{
   Guid id;
   string name;
}

The list contains multiple students. 该列表包含多个学生。 To search a student with specific id, I need to use foreach loop and compare id of each student. 要搜索具有特定ID的学生,我需要使用foreach循环并比较每个学生的ID。

I am looking for a better alternative instead of foreach loop. 我正在寻找一个更好的替代品而不是foreach循环。 Is there any alternative available? 有没有其他选择?

[EDIT]: What I meant by better alternative is optimized solution in terms of execution time and performance [编辑]:我所说的更好的替代方案是在执行时间和性能方面的优化解决方案

[EDIT2] One more twist, what if id is Guid. [EDIT2]还有一个转折,如果id是Guid怎么办?

Thanks, 谢谢,

Ram 内存

If each student can appear in the list only once, you might want to use a Dictionary<int, stutent> instead. 如果每个student只能在列表中出现一次,则可能需要使用Dictionary<int, stutent> Then you will have a very efficient way of looking up students by id. 那么你将有一个非常有效的方式来查找id的学生。

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

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

Nothing will really change the fact that you have to iterate over the list. 没有什么能真正改变你必须遍历列表的事实。 But you can use LINQ: 但你可以使用LINQ:

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

Based on an answer by @Fredrik Mörk, this could be shortened to: 根据@FredrikMörk的回答,这可以缩短为:

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

Also note, that Single() will throw an exception, if no student is found. 另请注意,如果找不到学生, Single()将抛出异常。 If you'd prefer to just return null , use SingleOrDefault() . 如果您只想返回null ,请使用SingleOrDefault()

But what you actually want to be doing is storing your students in a map: 但你真正想要做的是将学生存放在地图中:

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

This has a way better performance (O(1) for hashtables, O(log(n)) for trees) than looking through the list (O(n))! 这有一个更好的方式表现(O(1)哈希表,为O(log(n))的树木)比在列表中查找(O(n))的!

You can use LINQ: 您可以使用LINQ:

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

Enumerable.SingleOrDefault Method Enumerable.SingleOrDefault方法

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

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

Here's an idea, to avoid having to iterate over the list : 这是一个想法,以避免迭代列表:

  • Sort the list by Student.Id 按Student.Id对列表排序
  • Implement a more sophisticated search algorithm (eg Binary Search binary search ) 实现更复杂的搜索算法(例如二进制搜索二进制搜索

You can use any collection that uses hash lookup because their member look up is very quick. 您可以使用任何使用哈希查找的集合,因为它们的成员查找速度非常快。 eg Dictionary <K,V> , OrderedDictionary . 例如, Dictionary <K,V>OrderedDictionary There is also the nongeneric Hashtable which is mostly rendered redundant by the generic Dictionary<K,V> . 还有非泛型Hashtable ,它通常由泛型Dictionary<K,V>呈现为冗余。 In Big-O notation, element retrieval time by key for these collections is O(1) , which is as good as it gets. 在Big-O表示法中,按键获取这些集合的元素检索时间为O(1) ,这与它得到的一样好。

For accessing elements, to not incur the cost of two lookups, instead of using ContainsKey , you can use the TryGetValue method, eg: 要访问元素,不要使用两次查找,而不是使用ContainsKey ,您可以使用TryGetValue方法,例如:

Dictionary<Guid, Student> students = GetStudents();

Student student;
if (students.TryGetValue(guid, out student))
{
    // found
}

BTW, OrderedDictionary also allows you to access elements by index. BTW, OrderedDictionary还允许您通过索引访问元素。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM