Dylan Cole Duke
Dylan Cole Duke

Reputation: 65

Looking for highest value in array based on user input (C#)

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

Answers (3)

Dmitrii Bychenko
Dmitrii Bychenko

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

Christian M&#252;ller
Christian M&#252;ller

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

Daniel May
Daniel May

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

Related Questions