我的任务是下一个(在C#中): 我有一个包含数千个元素的列表 - 每个学生都有一个名字和一个年龄(7-18岁)。按照年龄,升序排列这个列表的重要事项。所以第一个元素就像一些7岁的学生。我必须尽快编写一个搜索功能(它现在并不重要),但为了使搜索功能更快,我被告知制作一个指向年龄的每个第一个元素的参考数组在我的学生列表中,实际上这个新数组将包含11个元素(让我们说每个年龄组中至少有一个孩子,这很可能),因为我会存储每年的第一个元素。
因此,每当我必须找到一位16岁的学生时,我可以先开始搜索ref数组,快速找到16岁的学生,这指向学生名单的16年老学生的第一个元素就在现场,没有毫无意义的迭代。我的问题是,如何告诉我的Student[] refArray()
提及每个第一个"年龄组"在学生名单中?
static Student[] refArray(List<Student> list_in)
{
int i = 7;
Student[] refArray = new Student[11];
// the size of the array is 11 since I'm assuming to get at least
// 1 student of each age groups, but I could just use a List or anything
foreach (Student stud in list_in)
{
if (stud.age == i)
{
refArray[i++] = stud;
}
}
return refArray;
}
我确定这是错误的代码可能是错误的,但我不知道如何以最简单的方式解决这个问题。另一个问题是,我真的不知道如果我找到了那个年龄的第一个学生,如何在学生名单中做出指向该对象的参考...
答案 0 :(得分:3)
最简单/最容易理解的方法是首先填充Dictonary<int, List<Student>>
并从那里查看。但是,由于您已有列表,因此可以使用Lookup
ToLookup
var lookup = studentsList.ToLookup(s => s.Age);
然后你可以像字典一样索引。例如,为了让所有8岁的学生:
var age8Students = lookup[8];
以下是此功能的一个很好的解释:DotNetPerls
答案 1 :(得分:2)
对于它的价值,我同意更好的数据结构将是最好的解决方案。也就是说,您可以使用LINQ查询来执行您正在查看的内容。假设您的学生列表已经按年龄排序(可能是按照其他类别排序,例如按年龄组中的姓氏按字母顺序排列)。
假设学生班级类似于:
public class Student
{
public int Age {get; set;}
public string Name {get; set;}
}
代码类似于:
var list = GetStudents(); // gets full list of students from somewhere, ordered by age, then name
var subList = new List<Student>(); // creates new empty list of students.
var ageList = list.Select(s => s.Age).Distinct().ToList(); // Gets a list of distinct age values
ageList.ForEach(s => subList.Add(list.First(p => p.Age == s)));
然后,变量subList将包含学生列表,每个学生都是每个年龄组中的第一个。获取学生列表中不同年龄的列表只能获得至少有一个学生的年龄,所以您的列表。首先应该永远不会遇到异常。
当然,这样做的一个缺点是,如果您的主要学生列表发生变化,您将需要重新生成您的子列表。
答案 2 :(得分:1)
到目前为止,使用Linq的答案都相当复杂。由于你不允许使用词典,我想你也不允许使用Linq。我认为这是以预期的精神回答了这个问题。请注意,我重命名了减少名称冲突的方法:
static int[] GetRefArray(List<Student> list_in)
{
int[] refArray = new int[11];
int referenceIndex = 0;
int dataIndex = 0;
int currentAge = int.MinValue;
foreach (Student stud in list_in)
{
if (stud.age != currentAge)
{
currentAge = stud.age;
refArray[referenceIndex++] = dataIndex;
}
dataIndex++;
}
return refArray;
}
现在,正如评论中所提到的,这种方法存在各种各样的问题。有一个简单的解决方案来处理列表插入的问题:每当你插入列表时丢弃引用数组,并在需要使用它时重新计算引用数组:
//we're about to use refArray to improve our lookup performance
if (refArray == null)
refArray = GetRefArray(studentList);
//use refArray here
和
//we're about to insert into the student list
refArray = null;
studentList.Insert(index, newStudent);
每当执行插入或删除操作时,您还可以修改refArray中的值。然而,要想做到这一点可能会很棘手,所以如果性能测试表明它是必要的(或者它是一个类赋值),我只会这样做。