How to search an element of an array and display - c#

I need to display the grade each student has by asking for it's number. The grade each student has is tied with each student, can be the array place of each. The Student number is what is prompted to ask the search in the array. Could it possibly be done in a short Two liner?
using System;
using System.Text;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
string[] studentName = {"Bob","Marie","Nathan","Lois","Sam"};
string[] studentsNumber = {"040707701","040707702","040707703","040707704","040707705"};
string[] studentGrade = {"A","B","C","D","F"};
string studentsNumber = "";
Console.WriteLine("What is your student number");
Console.ReadLine(studentsNumber.ToString());
for(int index = 0, studentNumber[studentNumber - 1], index++)
{
Console.WriteLine(studentsNumber[index]);
onsole.WriteLine(studentName[],studentGrade[] {0} {1});
}
}
}
}

Since this is homework, I'm not going to give you the answer outright but give you a hint instead.
Once you have the student number, loop through the array of student numbers. Once you find the index of the matching number...you can use that to retrieve the grade.
Keep in mind, though, that arrays aren't the right way to solve this problem at all. You'd be much better off creating a class for student that included name, number, and grade. You could then create instances of the class and add those instances to a List that you could then iterate through.

Would be much better to have an object:
public class StudentInfo
{
public string Name {get; set;}
public string Grade {get; set;}
public int Number {get; set;}
}
And then have a List<StudentInfo>.
By doing it this way your data will be tight together. Otherwise you might end up in a situation where you have different number of items in each array and you wouldn-t know which one is which.
Hope it helps.

eek!
Why not use an anonymous class with a bit of linq?
var students = new[]
{
new { Name = "Bob", Number = "040707701", Grade = "A" },
...
};
var grade = students.Where(s => s.Number == "040707701").Select(s => s.Grade);

Related

Indexes that correspond to each other in two Lists

I have two Lists:
List<string> names = new List<string>();
List<int> goals = new List<int>();
One of them is a string List while the other one is a int List. I add some numbers in the second List, and then I get the biggest number in the List. This works.
Now I need to type some names in the console and after each name I need to type a certain number and this repeats to whenever I want.
How do I get the index of the biggest number in the second list and to print it alongside the name that actually have "scored" that biggest number? I want to get the index from the first string List that corresponds to the index of the biggest number in the second List. Is there a way that I can do it?
In your case, "Name" and "Goals" relate to each other. Someone or something with a "Name" has obviously attached to them a number of "Goals". So, let's reflect this relation in a class:
public class StatisticsItem
{
// Properties here
public string Name {get; set;}
public int Goals {get; set;}
}
You then can create new instances of that class like so:
var item = new StatisticsItem() { Name = "Marc", Goals = 5 };
and you can put those in a list:
var myList = new List<StatisticsItem>();
myList.Add(item);
Find your champion:
using System.Linq;
// ...
Console.WriteLine("Goalie King: {0}", myList.MaxBy(x => x.Goals).Name);
See in action: https://dotnetfiddle.net/I9w5u7
To be a bit more clean, you could of course use a constructor:
public class StatisticsItem
{
// Properties here
public string Name {get; set;}
public int Goals {get; set;}
public StatisticsItem(string name, int goals)
{
Name = name;
Goals = goals
}
}
// and then create instances like so:
var item = new StatisticsItem("Marc", 5);
Can't comment so i will add my opinion here. Fildor suggested 1 list with 2 properties which should cover your case. I would say also check if a dictionary<string, int> or a dictionary<string, List<int>> is a better fit instead of a list.
Keep in mind for a dictionary to work the key (name in your case) must be unique. If not discard this answer

Deleting data from a list from a second form

I have a form that where I read in a csv file containing student information, the file has two columns StudentNumber and Mark. I want to allow the user to click a button on the first form to then go to another form called deleteRecord On this form the user will type in a StudentNumber and a Mark and the record that corresponds with them two pieces of information will be delete from the list.
Since I am new to C# I am not sure on how to go about this so any help will be appreciated.
My list:
public static List<string> studentInfo = new List<string>();
I store all the data from that list in a listbox called lstMarks
I want to also confirm to the user that the record was deleted successfully.
If all the data is stored in the list, simply use LINQ and add a number for each student in the list for the index.
First you'll need to create a class and (I recommend it) put it in a folder.
How it looks.
Then you'll have to put the propreties in the class:
public class Student
{
public int StudentNumber {get; set;}
public int Mark {get; set;}
public int Index {get; set;}
}
Now add another class with the list:
partial class MainWindow : Window
{
private List<Student> _studentInfo = new List<Student>()
{
new Student() {Index = 0, StudentNumber = 0, Mark = 0}
// ...
}
And then add using at the top of your code of deleteRecord and the name of the folder and the two classes:
using ExampleFolder.Class;
You'll need to call your Student class to be able to modify the StudentNumber and Mark and Index.
Student studentInfo = new Student();
int iIndex = 0;
var req = from info in studentInfo
where info.StudentNumber == txtStudentNumber && info.Mark == txtMarks
select info.Index; // Starts with 0 for the first student in the list
foreach(var num in req)
{
iIndex = num;
}
studentInfo.Remove(studentInfo[iIndex]);
MessageBox.Show("Deleted!");

Array sorting by class property in c# [duplicate]

Hope someone can help.
I have created a variable length array that will accept several name inputs.
I now want to sort the array in alphabetical order and return that to the console screen.
I thought that Array.Sort(names); would do this for me but I am getting an exception thrown. I have been looking at notes, examples and on-line but nothing seems to match what I am doing.
I have done the below so far. I am close to tearing my hair out here!
PS I have been trying to figure this out for hours and I am 30+ years old trying to learn myself, so please don't just say "Do your homework" I have tried to resolve this and can not so I need someone to explain where I am going wrong.
It is a Sunday and I am trying to do extra work and have no notes to cover this exactly
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Student_Array
{
class Program
{
struct Student
{
public string Name;
}
static void Main(string[] args)
{
int numberOfStudents;
Student[] names;
string input;
Console.WriteLine("How many students are there?");
input = Console.ReadLine();
numberOfStudents = int.Parse(input);
names = new Student[numberOfStudents];
for (int i = 0; i < names.Length; i++)
{
Student s;
Console.WriteLine("Please enter student {0}'s name", (i + 1));
s.Name = Console.ReadLine();
names[i] = s;
}
***Array.Sort<Student>(names);***
for (int i = 0; i < names.Length; i++)
{
Console.WriteLine(names[i].Name);
}
}
}
}
This shall do the trick
Array.Sort(names, (x,y) => String.Compare(x.Name, y.Name));
Your issue here might be that you are confusing the notions of students and names. By defining the Student struct, you are creating an entity that can represent more than a mere name. You could, for example, extend it to include Age, Hometown, and so forth. (For this reason, it might be more meaningful to name your array students rather than names.)
struct Student
{
public string Name;
public int Age;
public string Hometown;
}
Given the possibility of multiple fields, the Array.Sort method needs to know what you want to sort your list upon. Do you want students ordered by name, by age, or by hometown?
Per the MSDN documentation on Array.Sort<T>:
Sorts the elements in an entire Array using the IComparable<T> generic interface implementation of each element of the Array.
This means that the type you are attempting to sort – in your case, Student – must implement the IComparable<T> interface, in order for the Array.Sort implementation to know how it should compare two Student instances. If you're convinced that students will always be sorted by name, you could implement it like so:
struct Student : IComparable<Student>
{
public string Name;
public int Age;
public string Hometown;
public int CompareTo(Student other)
{
return String.Compare(this.Name, other.Name);
}
}
Alternatively, you could provide a function that extracts the sort key to the sort method itself. The easiest way of achieving this is through the LINQ OrderBy method:
names = names.OrderBy(s => s.Name).ToArray();
You can either use Sort as is if you extend Student to implement IComparable;
struct Student : IComparable<Student>
{
public string Name;
public int CompareTo(Student other)
{
return String.Compare(Name, other.Name,
StringComparison.CurrentCultureIgnoreCase);
}
}
...or you can pass a compare lambda into Sort...
Array.Sort<Student>(names, (x, y) => String.Compare(x.Name, y.Name,
StringComparison.CurrentCultureIgnoreCase));
...or as a third option just create a new, sorted, array;
var newArray = names.OrderBy(x => x.Name.ToLower()).ToArray();
You can use this as well, instead of using Array.Sort.
names = names.OrderBy(p => p.Name).ToArray();
Create a comparer class
class StudentComparer : IComparer<Student>
{
public int Compare(Student a, Student b)
{
return a.Name.CompareTo(b.Name);
}
}
Sort:
Array.Sort(students,new StudentComparer());
To sort by the name property of your Student objects in your Student array, you can use
Array.Sort(names, (s1, s2) => String.Compare(s1.Name, s2.Name));
which will sort your array in place, or with System.Linq:
names = names.OrderBy(s => s.Name).ToArray();
which can return the sorted IEnumerable as an array (.ToArray()) or a list (.ToList().)
Remember to sort case-insensitive if it matters, as pointed out in another answer, which can be done in String.Compare like so:
String.Compare(s1.Name, s2.Name, StringComparison.CurrentCultureIgnoreCase)
you can find one of the basics algorithms here : Simple bubble sort c#
you have to do some modifications , that example is for int, for string you must compare the names.
you can find better algorithms for sorting. for now bubble sort is ok for you.

Students students=(FileRoutines.LoadStudents(STUDENT_FILE));

I am taking a C# class and I have a project. The project has code written for void Main(). Here is the first part of the code in Main():
const string STUDENT_FILE = #"C:\TEMP\Students.txt";
const string ASSIGNMENT_FILE = #"C:\Temp\Assignments.txt";
Students students=FileRoutines.LoadStudents(STUDENT_FILE));
I have to write a 3 classes Students, student, and FileRoutines. I cannot seem to figure out what needs to go into the Students class to get the instance to work. I can write the following:
string[] students = FileRoutine.LoadStudents(STUDENT_FILE)
and get the students array I am trying to do with:
Students students=FileRoutines.LoadStudents(STUDENT_FILE));
but I cannot seem to get this instance to work. This is the contents of the file:
122338 Weltzer Teresa
123123 Wang Choo
123131 Adams James
123132 Binkley Joshua Troy
123139 Howard Tyler
123160 King Alma
I have seen this project posted before, but no one seems to be able to answer the question, but instead offer other alternatives.
I know when creating an instance of a class I need to have a constructor or constructors, but I am not doing:
Students students = new Students();
So far I am lost on what to do.
Thanks
Dave
To implement as you ask, FileRoutines.LoadStudents(STUDENT_FILE) has to return a Students instance, so you need to modify that method to construct the new Students and return that instead of string[]
So perhaps your Students class takes the string[] in its constructor?
That should be enough to get you going?
Obviously, the Students type has to behave like a collection of some kind. I propose this
A class for a student data is a piece of cake.
class Student
{
public string Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
Now things get a little more interesting. The following class implements IEnumerable of Student in order to provide the most crucial methods for looping through its inner structure. Is quite easy once you get this idea. You already store students in some collection so just return its enumerator instead of creating a custom one.
class Students : IEnumerable<Student>
{
private readonly List<Student> students;
public Students(IEnumerable<Student> students)
{
this.students = students.ToList();
}
public IEnumerator<Student> GetEnumerator()
{
return students.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return students.GetEnumerator();
}
}
And finally, a class with a method for loading from a file. This can be done many ways, but I find LINQ a nice tool for data querying.
class FileRoutines
{
public static Students LoadStudents(string path)
{
var lines = File.ReadLines(path);
var students = lines.Select(l => l.Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries))
.Select(split => new Student
{
Id = split[0],
LastName = split[1],
FirstName = split[2]
});
return new Students(students);
}
}

C# Finding element in List of String Arrays

I cannot solve a problem for several hours now.
Here is a simplified scenario.
Let's say there is a list of people with their bids. I'm trying to find a person with the highest bid and return the name. I am able to find the highest bid, but how to I output the name?
List<String[]> list = new List<String[]>();
String[] Bob = { "Alice", "19.15" };
String[] Alice = {"Bob", "28.20"};
String[] Michael = { "Michael", "25.12" };
list.Add(Bob);
list.Add(Alice);
list.Add(Michael);
String result = list.Max(s => Double.Parse(s.ElementAt(1))).ToString();
System.Console.WriteLine(result);
As a result I get 28.20, which is correct, but I need to display "Bob" instead. There were so many combinations with list.Select(), but no success. Anyone please?
The best solution from an architectural point of view is to create a separate class (e.g. Person) that contains two properties Name and Bid of each person and a class Persons that contains the list of persons.
Then you can easily use a LINQ command.
Also instead of storing bids as string, think if bids as floating point or decimal values would be better (or store it in cents and use an int).
I don't have a compiler by hand so it's a bit out of my head:
public class Person
{
public string Name { get; set; }
public float Bid { get; set; }
public Person(string name, float bid)
{
Debug.AssertTrue(bid > 0.0);
Name = name;
Bid = bid;
}
}
public class Persons : List<Person>
{
public void Fill()
{
Add(new Person("Bob", 19.15));
Add(new Person("Alice" , 28.20));
Add(new Person("Michael", 25.12));
}
}
In your class:
var persons = new Persons();
persons.Fill();
var nameOfHighestBidder = persons.MaxBy(item => item.Bid).Name;
Console.WriteLine(nameOfHighestBidder);
This works in the simple example. Not sure about the real one
var result = list.OrderByDescending(s => Double.Parse(s.ElementAt(1))).First();
You can use Jon Skeet's MaxBy.
For usage you can see this question
e.g. in this case
list.MaxBy(s => Double.Parse(s.ElementAt(1)))[0]
More here
Should work:
var max = list.Max(t => double.Parse(t[1]));
list.First(s => double.Parse(s[1]) == max)[0]; // If list is not empty
After finding result just do as below:
list.First(x=>x[1] == result)[0]

Categories