Reputation: 65
Student here.
Currently working on a project to find the highest value in an array based off users input.
The current foreach loop that I'm using takes the users input, then only finds the first instance that matches in the second array, instead of continuing to cycle through.
I've tried two ways. Both end up with the same result.
First I tried to create a list which then sorts and reverses. That way I can take the 0 index, and it be the highest
static void Main(string[] args)
{
string[] fishColors = new string[15] { "pink", "purple", "red", "orange", "blue", "green", "pink", "green", "blue", "red", "orange", "purple", "green", "red", "purple" };
int[] fishLengths = new int[15] { 49, 5, 45, 10, 14, 1, 44, 17, 48, 11, 13, 17, 20, 15, 37 };
List<int> userFishLengths = new List<int>();
int userChoice = 0;
string input = null;
int longestFish = 0;
do {
Console.WriteLine("Please select the number from the list below for the color of fish you would like to choose:\r\n0. Pink\r\n1. Purple\r\n2. Red\r\n3. Orange\r\n4. Blue\r\n5. Green");
input = Console.ReadLine();
} while (Int32.TryParse(input, out userChoice) == false) ;
string userColor = fishColors[userChoice];
foreach (string fish in fishColors)
{
if (userColor == fish)
{
int indexID = Array.IndexOf(fishColors, fish);
int fishLength = fishLengths[indexID];
userFishLengths.Add(fishLength);
}
}
userFishLengths.Sort();
userFishLengths.Reverse();
Console.WriteLine("The longest fish in the tank with the color you chose (" + userColor + ") is " + userFishLengths[0]+" inches.");
}
Second, I tried to create a value that takes it in each time, and overwrites the variable if it's larger.
static void Main(string[] args)
{
string[] fishColors = new string[15] { "pink", "purple", "red", "orange", "blue", "green", "pink", "green", "blue", "red", "orange", "purple", "green", "red", "purple" };
int[] fishLengths = new int[15] { 49, 5, 45, 10, 14, 1, 44, 17, 48, 11, 13, 17, 20, 15, 37 };
int userChoice = 0;
string input = null;
int longestFish = 0;
do {
Console.WriteLine("Please select the number from the list below for the color of fish you would like to choose:\r\n0. Pink\r\n1. Purple\r\n2. Red\r\n3. Orange\r\n4. Blue\r\n5. Green");
input = Console.ReadLine();
} while (Int32.TryParse(input, out userChoice) == false) ;
string userColor = fishColors[userChoice];
foreach (string fish in fishColors)
{
if (userColor == fish)
{
int indexID = Array.IndexOf(fishColors, fish);
int fishLength = fishLengths[indexID];
if (fishLength > longestFish)
{
longestFish = fishLength;
}
}
}
Console.WriteLine("The longest fish in the tank with the color you chose (" + userColor + ") is " + longestFish + " inches.");
}
Any help/suggestions would be appreciated. Thank you!
Upvotes: 2
Views: 283
Reputation: 186668
I know, that it's student project; however the problem is that very one Linq has been designed for
string[] fishColors = new string[] //DONE: you have no need in specifing magic number "15"
{ "pink", "purple", "red", "orange", "blue", "green", "pink", "green", "blue",
"red", "orange", "purple", "green", "red", "purple" };
int[] fishLengths = new int[] //DONE: you have no need in specifing magic number "15"
{ 49, 5, 45, 10, 14, 1, 44, 17, 48, 11, 13, 17, 20, 15, 37 };
// Color/its index correspondence:
// Key - index: 1, 2, 3, ...
// Value - color: pink, purple, red, ...
var colors = fishColors
.Distinct()
.Select((color, index) => new {
color = color,
index = index + 1, })
.ToDictionary(item => item.index, item => item.color);
string userColor = null;
while (true) {
Console.WriteLine("Please select the number from the list below for the color of fish you would like to choose:");
//DONE: instead of hardcoding, build the string
Console.WriteLine(string.Join(Environment.NewLine, colors
.OrderBy(pair => pair.Key)
.Select(pair => $"{pair.Key}. {pair.Value}")));
//DONE: input is valid if and only iff it's integer and it corresponds to color
if (int.TryParse(Console.ReadLine(), out var code) && // <- out var - C# 7.0 Syntax
colors.TryGetValue(code, out userColor))
break;
}
//DONE: zip colors and lengths, filter out userColor fish only, get maximum
var result = fishColors
.Zip(fishLengths, (color, length) => new { color = color, length = length })
.Where(item => item.color == userColor)
.Max(item => item.length);
//DONE: do not concat string, but use string interpolation (or formatting)
Console.WriteLine($"The longest fish in the tank with the color you chose ({userColor}) is {result} inches.");
Upvotes: 0
Reputation: 1022
your script didn't work, because you using:
int indexID = Array.IndexOf(fishColors, fish);
Which always give you the first match and not the current pair.
Example: You searching "purple" and getting always the entry 5.
If I didn't want to change you code much, then this would be changed version:
static void Main(string[] args)
{
string[] fishColors = new string[15] { "pink", "purple", "red", "orange", "blue", "green", "pink", "green", "blue", "red", "orange", "purple", "green", "red", "purple" };
int[] fishLengths = new int[15] { 49, 5, 45, 10, 14, 1, 44, 17, 48, 11, 13, 17, 20, 15, 37 };
int userChoice = 0;
string input = null;
int longestFish = 0;
do
{
Console.WriteLine("Please select the number from the list below for the color of fish you would like to choose:\r\n0. Pink\r\n1. Purple\r\n2. Red\r\n3. Orange\r\n4. Blue\r\n5. Green");
input = Console.ReadLine();
} while (Int32.TryParse(input, out userChoice) == false);
string userColor = fishColors[userChoice];
int indexID = 0;
foreach (string fish in fishColors)
{
if (userColor == fish)
{
int fishLength = fishLengths[indexID];
if (fishLength > longestFish)
{
longestFish = fishLength;
}
}
indexID++;
}
Console.WriteLine("The longest fish in the tank with the color you chose (" + userColor + ") is " + longestFish + " inches.");
Console.ReadKey();
}
But with LINQ you could make it more simple:
static void Main(string[] args)
{
string[] fishColors = new string[15] { "pink", "purple", "red", "orange", "blue", "green", "pink", "green", "blue", "red", "orange", "purple", "green", "red", "purple" };
int[] fishLengths = new int[15] { 49, 5, 45, 10, 14, 1, 44, 17, 48, 11, 13, 17, 20, 15, 37 };
int userChoice = 0;
string input = null;
int longestFish = 0;
do
{
Console.WriteLine("Please select the number from the list below for the color of fish you would like to choose:\r\n0. Pink\r\n1. Purple\r\n2. Red\r\n3. Orange\r\n4. Blue\r\n5. Green");
input = Console.ReadLine();
} while (Int32.TryParse(input, out userChoice) == false);
string userColor = fishColors[userChoice];
longestFish = fishColors
.Zip(fishLengths, (color, length) => new { color, length })
.Where(s => s.color.Equals(userColor)).Max(x => x.length);
Console.WriteLine("The longest fish in the tank with the color you chose (" + userColor + ") is " + longestFish + " inches.");
Console.ReadKey();
}
Upvotes: 0
Reputation: 8226
The problem lies in your Array.IndexOf()
call.
int indexID = Array.IndexOf(fishColors, fish);
The contents of your fishColors
array are not unique, and thus the Array.IndexOf(fishColors, fish)
call is simply returning the index of the first matching element. (e.g. "pink" = 0
, "red" = 2
)
You would be better suited using a different data structure to store these values. Look into using a Dictionary<TKey,TValue>
, e.g.
var fish = new Dictionary<string, int[]>()
{
{ "pink", new[] { 49, 44 } },
{ "purple", new[] { 5, 17, 37 } }
};
This would give you an easier way to look up the lengths associated with the colors.
Alternatively, if you must retain the use of both arrays, you can do this with a simple for
loop instead of a foreach
.
for (int i = 0; i < fishColors.Length; i++)
{
if (userColor == fishColors[i])
{
int fishLength = fishLengths[i];
if (fishLength > longestFish)
{
longestFish = fishLength;
}
}
}
Upvotes: 1