Doing a college project and I\'m a bit stuck..
Basically, I need to take the string input for an employee name and an integer input for the amount of properties they sol
I have stored the name and properties sold in their own separate lists, I know how to sort the number list in size order but then how do I link it back with the appropriate name?
The other answers give mostly good advice. Summing up, it is:
However it is worth pointing out that there are also methods to answer your question directly, namely, how do I sort one list by the elements of another list?
Method one
Once you have built both lists, use ToArray
on both of them. Then use the overload of Array.Sort
which takes two arrays, one of keys, and one of value, but sorts both of them by the key array:
https://docs.microsoft.com/en-us/dotnet/api/system.array.sort?view=netframework-4.8#System_Array_Sort_System_Array_System_Array_System_Int32_System_Int32_
Method two
Suppose you have elements numbered 0, 1, 2, 3 in both lists. Create that sequence of numbers:
var indices = Enumerable.Range(0, names.Length);
Now sort that sequence by the corresponding value:
var sortedIndices = indices.OrderBy(i => numbers[i]);
Make sure this step is clear. If we have numbers 40, 30, 10, 20
then we are ordering the numbers 0, 1, 2, 3 by the corresponding values in this sequence, so we will get 2, 3, 1, 0.
Now we can transform that into a sequence of names!
var sortedNames = sortedIndices.Select(i => names[i]).ToList();
Method three
Use the Zip
sequence operator to form a "zipper join". That is, join up the two sequences like the teeth meshing in a zipper. Then order the sequence of pairs by the number, and then extract the sorted sequence of names:
var sorted = names.Zip(numbers, (name, number) => (name, number))
.OrderBy(p => p.number)
.Select(p => p.name)
.ToList();
I strongly recommend that you make a study of the operations you can perform on sequences in C#. They are extremely powerful tools.
Probably the easiest way is to store the values together in a single list, by creating a simple class to hold them:
public class Realtor
{
public string Name { get; set; }
public int PropertiesSold { get; set; }
}
Then you can populate instances of this class from the user input, add them to a list, and then use the linq extenstion method OrderByDescending
to order the items by the realtor.PropertiesSold
property:
public static void Main(string[] args)
{
var realtors = new List<Realtor>();
for (var i = 0; i < 3; i++)
{
var realtor = new Realtor();
Console.Write("Please enter the employee name: ");
realtor.Name = Console.ReadLine();
realtor.PropertiesSold = GetIntFromUser(
"Please enter the number of Properties Sold: ", x => x >= 0);
realtors.Add(realtor);
Console.WriteLine();
}
realtors = realtors.OrderByDescending(realtor => realtor.PropertiesSold).ToList();
Console.WriteLine("Results in order of most properties sold:\n");
Console.WriteLine($"{"Name".PadRight(10)} Properties Sold");
Console.WriteLine($"{new string('-', 10)} {new string('-', 15)}");
foreach (var realtor in realtors)
{
Console.WriteLine($"{realtor.Name.PadRight(10)} {realtor.PropertiesSold}");
}
GetKeyFromUser("\nDone! Press any key to exit...");
}
Sample Output
Note
The sample code above uses a method called GetIntFromUser
to get the number of properties sold. The reason for this is that we can't expect that the users will always enter a valid number, so we want to do some validation on it first.
The method (below) takes in a string
that is used to prompt the user for input, and it takes an optional validation function that can be used to ensure that the value they enter is allowed (in the sample above, I specified that the value must be greater than or equal to zero).
Here is the method used in the sample above:
public static int GetIntFromUser(string prompt, Func<int, bool> validator = null)
{
int result;
var cursorTop = Console.CursorTop;
do
{
ClearSpecificLineAndWrite(cursorTop, prompt);
} while (!int.TryParse(Console.ReadLine(), out result) ||
!(validator?.Invoke(result) ?? true));
return result;
}
private static void ClearSpecificLineAndWrite(int cursorTop, string message)
{
Console.SetCursorPosition(0, cursorTop);
Console.Write(new string(' ', Console.WindowWidth));
Console.SetCursorPosition(0, cursorTop);
Console.Write(message);
}
Use structs or a dictionary. I won't give you a line by line answer because it's an assignment and you need the problem solving practice but here is the steps:
Read in the name and number like you are already. Rather than storing them in separate lists, create a new struct for each person with their number of properties sold and their name (Or put them in a dictionary key-value pair).
Then you can sort the list (or dictionary) and print it out. Each item in the list/dictionary is guaranteed to be associated with the right data if you put them in right in the first place.
you can use the dictionary to implementing this senario
Dictionary<string, int> users = new Dictionary<string, int>();
for (int i = 0; i < 2; i++)
{
Console.WriteLine("Please enter the employee name: ");
string name = Console.ReadLine();
Console.WriteLine("Please enter the number of Properties Sold: ");
int number = int.Parse(Console.ReadLine());
users.Add(name, number);
}
var data = users.OrderByDescending(a => a.Value).ToList();
foreach (var i in data)
{
Console.WriteLine(i.Key+" "+i.Value);
}
Ideally you would be using a class for these, as seen in the example below.
public class Owner
{
public string Name { get; }
public int PropertiesSold { get; }
public Owner(string name, int propertiesSold)
{
Name = name;
PropertiesSold = propertiesSold;
}
}
This way you can keep track of the name and # of properties at the same time. Your loop turns into this:
List<Owner> owners = new List<Owner>();
for (int i = 0; i < 2; i++)
{
Console.WriteLine("Please enter the employee name: ");
string name = Console.ReadLine();
Console.WriteLine("Please enter the number of Properties Sold: ");
int numProperties = int.Parse(Console.ReadLine());
owners.Add(new Owner(name, numProperties));
}
And you can use Linqs OrderByDescending as seen here to sort the list of Owners. LINQ Orderby Descending Query.