从另一个数组创建引用数组

本文关键字:数组 引用 创建 另一个 | 更新日期: 2023-09-27 18:01:02

我的任务是下一个(在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;
    }

我真的很确定这是一个错误的代码可能是错误的,但我不知道如何解决这个最简单的方法。另一个我真的不知道的问题是,如果我找到了第一个那个年龄的学生,如何在学生列表中引用那个对象。。。

从另一个数组创建引用数组

实现这一点最不复杂/最容易理解的方法是从填充Dictonary<int, List<Student>>开始,然后从那里进行查找。但是,由于您已经有了一个列表,您可以使用ToLookup 创建一个Lookup

var lookup = studentsList.ToLookup(s => s.Age);

然后你就可以像字典一样编入索引了。例如,要获得所有8岁以下的学生:

var age8Students = lookup[8];

下面是对这个函数的一个很好的解释:DotNetPerls

就其价值而言,我同意更好的数据结构将是最好的解决方案。也就是说,你可以使用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)));

然后,变量子列表将包含一个学生列表,每个学生都是每个年龄组中的第一个。在你的学生列表中获取不同年龄的列表只会得到至少有一个学生的年龄,所以你的列表。第一个永远不应该遇到例外。

当然,这样做的一个缺点是,如果你的学生主列表发生了变化,你需要重新生成你的子列表。

到目前为止,这两个答案都相当复杂,都使用了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中的值。然而,这可能很难做到正确,所以我只会在性能测试表明有必要的情况下(或者如果这是一个类作业(才这么做。