C#如何在用户输入中使用词典和列表?

时间:2017-09-06 22:07:26

标签: c# dictionary

我正在建立一个我已经创建的项目。这是我第一次尝试使用词典/列表。这是一个非常广泛的问题,因为我的书根本没有涉及使用词典,而且我无法在线查找带有用户输入的词典示例。我使用多维数组制作了一个程序,要求用户提供一些学生和一些考试,然后用户输入每个考试的分数,并根据考试分数输出每个学生的平均成绩。我现在想要实现同样的事情,只使用字典和列表而不是数组。我甚至不知道从哪里开始。任何人都可以解释这是如何工作的?这是我已经创建的代码,虽然它可能根本没有帮助:

class MainClass
{
    public static void Main(string[] args)
    {
        int TotalStudents = 0;
        int TotalGrades = 0;

        Console.WriteLine("Enter the number of students: ");
        TotalStudents = Convert.ToInt32(Console.ReadLine());

        Console.WriteLine("Enter the number of exams: ");
        TotalGrades = Convert.ToInt32(Console.ReadLine());

        int[,] scoresArray = new int[TotalStudents, TotalGrades];

        for (int r = 0; r < TotalStudents; r++)
            for (int c = 0; c < TotalGrades; c++)
            {
            Console.Write("Please enter exam score {0} for student {1}: ", c + 1, r + 1);
                scoresArray[r, c] = Convert.ToInt32(Console.ReadLine());
            }
        for (int r = 0; r < scoresArray.GetLength(0); r++)
        {
            int studentSum = 0;
            int testCount = 0;
            for (int c = 0; c < scoresArray.GetLength(1); c++)
            {
                studentSum += scoresArray[r, c];
                testCount++;
            }
            string gradeLetter = "";
            double average = studentSum / testCount;
            Console.WriteLine("\nStudent " + (r + 1).ToString() + " Average Score: " + average.ToString());

            if (average >= 90)
            {
                gradeLetter = "A";
            }
            else if (average >= 80 && average < 90)
            {
                gradeLetter = "B";
            }
            else if (average >= 70 && average < 80)
            {
                gradeLetter = "C";
            }
            else if (average >= 60 && average < 70)
            {
                gradeLetter = "D";
            }
            else
            {
                gradeLetter = "F";
            }

            Console.WriteLine("Student " + (r + 1).ToString() + " will recieve a(n) " + gradeLetter + " in the class.\n");
        }
        Console.Write("\nPress the [ENTER] key to exit.");
        Console.ReadLine();
    }
}

3 个答案:

答案 0 :(得分:1)

字典是一个很棒的工具!我试图使用你原来的逻辑,但有时,我不得不采取另一种方式。此外,我一直迷失在&#34; c&#34;和&#34; r&#34;索引变量。我更喜欢索引的名字。希望这会有所帮助。

//Let's create a gradeTranslator dictionary.
// As the grades follow the simple divisions along averages divisible by 10,
// we can just use the first digit of the average to determine the grade.


using System;
using System.Collections.Generic;
using System.Linq;


namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            bool useSampleData = true;
            Dictionary<string, List<double>> gradeBook = new Dictionary<string, List<double>>();
            Dictionary<int, string> gradeTranslator = new Dictionary<int, string>();

            for (int i = 0; i < 6; i++) {
                gradeTranslator.Add(i, "F");
            }
            gradeTranslator.Add(6, "D");
            gradeTranslator.Add(7, "C");
            gradeTranslator.Add(8, "B");
            gradeTranslator.Add(9, "A");
            gradeTranslator.Add(10, "A");

            int TotalStudents, TotalGrades;

            // For testing purposes, it is a lot easier to start with some
            // sample data. So, I created a query to see if the user wants 
            // to use sample data or to provide her own input.
            Console.WriteLine("Do you want to input the data (I) or allow me to use sample data (S)?");
            var inputMethod = Console.ReadLine();

            if(inputMethod.ToUpper().IndexOf("I") >=0) {
                useSampleData = false; 
            }

            // User Sample Data   
            if (useSampleData) {  // test without using the console input
                gradeBook.Add("Bob", new List<double>() { 67.8, 26.3, 33.2, 33.1, 67.2 });
                gradeBook.Add("Dick", new List<double>() { 88.2, 45.2, 100.0, 89.2, 91.5 });
                gradeBook.Add("Jane", new List<double>() { 99.2, 99.5, 93.9, 98.2, 15.0 });
                gradeBook.Add("Samantha", new List<double>() { 62, 89.5, 93.9, 98.2, 95.0 });
                gradeBook.Add("Estefania", new List<double>() { 95.2, 92.5, 92.9, 98.2, 89 });

                TotalStudents = gradeBook.Count();
                TotalGrades = gradeBook["Bob"].Count();

                TotalStudents = 5;

            // user will provide their own data.
            } else { 

                Console.WriteLine("Enter the number of students: ");
                TotalStudents = Convert.ToInt32(Console.ReadLine());

                Console.WriteLine("Enter the number of exams: ");
                TotalGrades = Convert.ToInt32(Console.ReadLine());



                for (int studentId = 0; studentId < TotalStudents; studentId++) {
                    Console.Write("Please enter name of student {0}: ", studentId);
                    var name = Console.ReadLine();
                    gradeBook.Add(name, new List<double>());
                    for (int testId = 0; testId < TotalGrades; testId++) {
                        Console.Write("Please enter exam score {0} for " + 
                        "student {1}: ", testId + 1, name);
                         gradeBook[name].
                         Add(Convert.ToDouble(Console.ReadLine()));
                    }
                }

            }

            // Here we will divide the grade by 10 as an integer division to
            // get just the first digit of the average and then translate
            // to a letter grade.
            foreach (var student in gradeBook) {
                Console.WriteLine("Student " + student.Key + 
             " scored an average of " + student.Value.Average() + ". " + 
              student.Key + " will recieve a(n) " + 
              gradeTranslator[(int)(student.Value.Average() / 10)] + 
                              " in the class.\n");
            }

            Console.Write("\nPress the [ENTER] key to exit.");
            Console.ReadLine();
        }
    }
}

答案 1 :(得分:0)

建立学生班级以保存信息。

public class Student
{
  public string ID
  public List<double> TestScores {get;set;}
  // in this case average only has a getter which calculates the average when needed.
  public double Average 
  {
      get
      { 
       if(TestScores != null && TestScores.Count >0)
         {
           double ave = 0;
           foreach(var x in TestScores)//basic average formula.
              ave += x;
           // using linq this could be reduced to "return TestScores.Average()"
           return ave/TestScores.Count;
         }
         return 0; // can't divide by zero.
      }

  }
  public Student(string id)
  {
   ID = id;
   TestScores = new List<double>();
  }

}

现在您的词典集合可以保留信息。为了帮助您入门,有几种方法可以访问数据。绝对不是全包。

向字典中添加元素:

Dictionary<string,Student> dict = new Dictionary<string,Student>();
Student stud = new Student("Jerry");
dict.Add(stud.ID,stud);

提取信息:

string aveScore = dict["Jerry"].Average.ToString("#.00");
Console.Write(aveScore);

循环通过字典:

foreach(var s in dict.Keys)
{
   dict[s].TestScores.Add(50);
}

答案 2 :(得分:0)

由于这是家庭作业,或者您正在尝试学习如何使用词典,而不是发布代码,我只会指出正确的方向。

C#中的Dictionary是键值对的集合。 Key必须是唯一的,Value不一定是Dictionary<int, int> dict = new Dictionary<int, int>(); 。因此,如果您按如下方式定义字典:

Key

这意味着您已创建了一组对,其中int的类型为Valueint的类型为index = 0。因此,如果您向字典添加几个项目,它的内容将如下所示:

enter image description here

Key=1,您有一个包含Value=100index = 1的项目。 在Key=2,您有一个包含Value=200Value的项目。

但是,字典的Collection不一定必须是单个值。它也可以是Value(或类对象,甚至是另一个字典)。

由于您的要求是每个学生都有一个分数列表,并且字典Collection允许Dictionary<string, List<int>>,因此使用字典看起来确实是一个好主意。但是我们应该使用什么样的字典?

嗯,有很多可供选择。

一种方法是使用string。表示学生姓名(或ID)的List<int>和表示考试成绩的Dictionary<string, List<int>> dict = new Dictionary<string, List<int>>(); 。所以;

dict.Add("Arthur Dent", new List<int>() { 75, 54, 26 });
dict.Add("Zaphod Beeblebrox", new List<int>() { 12, 13, 7 });
dict.Add("Ford Prefect", new List<int>() { 99, 89, 69 });

现在,您可以使用每个学生的分数填充此词典。例如:

Value

在您的情况下,您可以从用户那里获得每个学生姓名和分数的输入。

但是,就像我说的那样,你也可以使用类对象作为字典Student,事实上,这是一个更好的方法来解决你的问题。 Felix的答案显示了如何做到这一点,所以我不会详细介绍。但是你基本上想要创建一个字典如下,假设你的类是Dictionary<string, Student> dict = new Dictionary<string, Student>();

Student

然后根据用户输入创建Student的实例,并将它们添加到字典中。使用Average()类的另一个好处是,您可以在一个地方获得与一个学生相关的所有信息,并且还有其他帮助方法,例如Felix示例中的def plot(log_name,num): numbers = [ random.randint(1,20) for _ in range(10) ] fig = plt.figure() ## crashes here, with no error ax = fig.add_subplot(1,1,1) ax.plot(numbers ,numbers ,label="test1") ax.plot(numbers , numbers , label="test2") ax.set_xlabel('Test1') ax.set_ylabel('Test2') ax.legend() fig.savefig("figures/"+str(num)+".png") plt.close(fig) if __name__ == '__main__': freeze_support() ## Single process works. A figure is generated #plot("1",1) ## Multiprocesses doesnt work. No figures will be generated p1 = Process(target=plot,args=("1",1)) p1.start() p2 = Process(target=plot, args=("2", 2)) p2.start() p1.join() p2.join() 方法,因此您的代码将更清洁,更简单。