【问题标题】:Summing up values in jagged array对锯齿状数组中的值求和
【发布时间】:2012-12-04 21:13:04
【问题描述】:

我有一个用于获取学生和学科详细信息的锯齿状数组,我使用了 2 个锯齿状数组,一个用于学生详细信息(姓名和卷号),另一个用于学科详细信息(学科和分数),现在我想总结一下特定学生的所有分数,谁能告诉我我该怎么做,下面是我的完整代码。

public void GetStudentDetails()
        {

            Console.WriteLine("Please enter number of Students");
            int STUDENTS = Convert.ToInt32(Console.ReadLine());
            Console.WriteLine("Please enter number of Subjects");
            int SUBJECTS = Convert.ToInt32(Console.ReadLine());    //0 is reserved for the student name, so the marks starts from the index 1, hence if you set the marks for 3, it will ask for 2 marks


            string[][] student_details = new string[STUDENTS][];
            string[][] subject_details = new string[SUBJECTS][];
            string[][] result_details = new string[STUDENTS][];

            StringBuilder stud_sub_info = new StringBuilder();
            stud_sub_info.Append("Name\tRoll-No\t");
            for (int a = 0; a < STUDENTS; a++)
            {
                student_details[a] = new string[STUDENTS * 2];
                for (int b = 0; b < 2; b++)
                {
                    Console.WriteLine("Enter Student {0} {1}:", a + 1, (b == 0) ? "Name" : "Roll-No");
                    student_details[a][b] = Console.ReadLine();
                }
                for (int c = 0; c < SUBJECTS; c++)
                {
                    subject_details[c] = new string[SUBJECTS * 2];
                    for (int d = 0; d < 2; d++)
                    {
                        if (d == 0)
                        {
                            Console.WriteLine("Enter Name for Subject {0}", c + 1);
                            subject_details[c][d] = Console.ReadLine();
                            stud_sub_info.Append(subject_details[c][d] + "\t");
                        }
                        else
                        {
                            Console.WriteLine("Enter Marks for {0}", subject_details[c][d - 1]);
                            subject_details[c][d] = Console.ReadLine();
                        }
                    }
                }
            }
            Console.WriteLine(stud_sub_info.ToString());
            for (int a = 0; a < STUDENTS; a++)
            {
                for (int b = 0; b < 2; b++)
                {
                    Console.Write(student_details[a][b] + "\t");
                }
                for (int c = 0; c < SUBJECTS; c++)
                {
                    for (int d = 0; d < 2; d++)
                    {
                        Console.Write(subject_details[c][d] + "\t");
                    }
                }
            }
        }

【问题讨论】:

    标签: c# .net sum jagged-arrays


    【解决方案1】:

    使用 Linq、Collections 和创建类而不是交错数组会容易得多。这将允许您将 1 个学生链接到许多课程,并且在每个课程中都有许多作业。然后是 Linq 语句如:

    Sum(x => x.StudentGrade)
    

    以下是我将开始使用的存根副本,只是为了了解我可以用总和和其他信息做什么:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace StudentManagement {
      public class Student {
    
        public static void Main(string[] args) {
          List<Student> students = new List<Student>();
    
          Console.Write("Enter number of students: ");
          int numStudents = int.Parse(Console.ReadLine());
    
          for (int i = 0; i < numStudents; i++) {
            Student s = new Student();
            students.Add(s);
          }
    
          Console.Write("Press any key to continue...");
          Console.ReadKey(true);
        }
    
        public string FirstName { get; set; }
        public List<Course> Courses { get; set; }
    
        public Student() {
          this.Courses = new List<Course>();
    
          Console.Write("Enter First Name: ");
          this.FirstName = Console.ReadLine();
    
          Console.Write("Enter in number of courses: ");
          int numCourses = int.Parse(Console.ReadLine());
    
          for (int i = 0; i < numCourses; i++) {
            Course course = new Course();
            this.Courses.Add(course);
          }
    
        }
      }
    
      public class Course {
        public string Title { get; set; }
        public string Code { get; set; }
        public string Section { get; set; }
        public List<Assignment> Assignments { get; set; }
    
        public Course() {
          this.Assignments = new List<Assignment>();
    
          // Set Title, Code, Section
          Console.Write("Enter nuber of assignments: ");
          int numAssignments = int.Parse(Console.ReadLine());
    
          for ( int i = 0; i < numAssignments; i++) {
            Assignment assignment = new Assignment();
            this.Assignments.Add(assignment);
          }
    
        }
      }
    
      public class Assignment {
        public string Name { get; set; }
        public double MaxGrade { get; set; }
        public double StudentGrade { get; set; }
    
        public Assignment() {
          // Prompt for Name, MaxGrade, StudentGrade
        }
      }
    }
    

    【讨论】:

    • 我完全同意,大量数组的代码花了我 5 分钟来理解,又花了 5 分钟来决定我是否有足够的精力来撰写建设性的答案。 +1 给你。
    • 有趣的是,我的学生两周前在课堂上完成了这项作业,当时我们正在通过集合和 Linq 进行所有权链接。
    • @Damon:如果你不介意你能告诉我循环将如何进行以获取用户的输入,我也认为你的代码会优化性能。
    • @Abbas 我刚刚编辑了昨天的帖子,向您展示了在代码中放置循环的位置。我没有输入代码来生成总和之类的东西。这应该足以让您继续前进。
    【解决方案2】:

    我当然不会使用这样的锯齿状数组。这使得编码变得困难。

    例如,在您的代码中,您正在捕获每个学生的科目分数,但是当您这样做时,您会清除以前学生的数据。 subject_details 锯齿状数组没有学生索引。您正在有效地覆盖数据。您需要将数组声明为string[][][]

    这是你的代码,更简单,可以工作:

    string[][] student_details = new string[STUDENTS][];
    string[][][] subject_details = new string[STUDENTS][][];
    string[][] result_details = new string[STUDENTS][];
    
    for (int a = 0; a < STUDENTS; a++)
    {
        student_details[a] = new string[STUDENTS * 2];
        subject_details[a] = new string[SUBJECTS][];
        Console.WriteLine("Enter Student {0} {1}:", a + 1, "Name");
        student_details[a][0] = Console.ReadLine();
        Console.WriteLine("Enter Student {0} {1}:", a + 1, "Roll-No");
        student_details[a][1] = Console.ReadLine();
        for (int c = 0; c < SUBJECTS; c++)
        {
            subject_details[a][c] = new string[SUBJECTS * 2];
            Console.WriteLine("Enter Name for Subject {0}", c + 1);
            subject_details[a][c][0] = Console.ReadLine();
            Console.WriteLine("Enter Marks for {0}", subject_details[a][c][0]);
            subject_details[a][c][1] = Console.ReadLine();
        }
    }
    for (int a = 0; a < STUDENTS; a++)
    {
        Console.Write(student_details[a][0] + "\t");
        Console.Write(student_details[a][1] + "\t");
        for (int c = 0; c < SUBJECTS; c++)
        {
            Console.Write(subject_details[a][c][0] + "\t");
            Console.Write(subject_details[a][c][1] + "\t");
        }
    }
    

    现在,鉴于我们忽略了每个学生必须拥有相同数量的科目并且您允许科目分数的非数字输入这一事实,您可以使用以下 LINQ 查询将锯齿状数组转换为可行的数组。

    var query =
        from i in Enumerable.Range(0, STUDENTS)
        let Name = student_details[i][0]
        let RollNo = student_details[i][1]
        let Subjects = (
            from j in Enumerable.Range(0, SUBJECTS)
            let Subject = subject_details[i][j][0]
            let Marks = int.Parse(subject_details[i][j][1])
            select new { Subject, Marks }
        )
        select new { Name, RollNo, Subjects };
    

    这给了我一个看起来像这样的结构:

    现在您可以使用此查询来获取总分:

    var results =
        query
            .Select(x => new
            {
                x.Name,
                TotalMarks = x.Subjects.Sum(y => y.Marks)
            });
    

    现在看起来像:

    【讨论】:

    • 你的代码就像一个魅力,虽然需要小改动 student_details[STUDENT * 2] 和 subject_details[SUBJECT * 2],但在这两种情况下 (*2) 都不是必需的,因为它会创建空白数组中的索引,一切都很好,最好的部分是它比我的更整洁
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-23
    • 2020-04-02
    • 1970-01-01
    • 2017-09-21
    • 2013-04-21
    • 2012-03-20
    相关资源
    最近更新 更多