0

I have to make an array of n elements, and find out how many times each number appears, like this:

Array: (-1.7 ; 3.0 ; 0.0 ; 1.5 ; 0.0 ; -1.7 ; 2.3 ; -1,7)
-1.7 appears 3 times
 3.0 appears 1 time
 0.0 appears 2 times
 1.5 appears 1 time
 2.3 appears 1 time

I have tried it, and my code looks like this:

        int n = 0;
        Console.WriteLine("Type in the size of your array...");
        n = int.Parse(Console.ReadLine());

        float[] vet = new float[n];
        int[] freq = new int[n];

        Console.WriteLine("Now, type in each element...");
        for(int i = 0; i < vet.Length; i++)
        {
            Console.Write("Position {0}: ", i);
            vet[i] = float.Parse(Console.ReadLine());
        }
        for(int j = 0; j< vet.Length; j++)
        {
            for(int k = 0; k< freq.Length; k++)
            {
                if(vet[j] == vet[k])
                {
                    freq[j]++;
                }
            }
        }
        Console.WriteLine("The number of times each element appears in the array is:");

        for(int l = 0; l< freq.Length; l++)
        {
            Console.WriteLine("{0} appears {1} time(s)", vet[l], freq[l]);
        }
        Console.ReadKey();

But the output stays like this:

The number of times each element appears in the array is:
-1.7 appears 3 time(s)
 3.0 appears 1 time(s)
 0.0 appears 2 time(s)
 1.5 appears 1 time(s)
 0.0 appears 2 time(s)
-1.7 appears 3 time(s)
 2.3 appears 1 time(s)
-1.7 appears 3 time(s)

My question is: How can I make my code works in a way that repeated numbers are printed once, like the first example?

Erik Philips
  • 53,428
  • 11
  • 128
  • 150
Rune Hobbo
  • 21
  • 1
  • 7

4 Answers4

3

I personally would use linq like:

    decimal[] values = {-1.7m , 3.0m , 0.0m , 1.5m , 0.0m , -1.7m , 2.3m , -1,7m};
    
    var result = values
        .GroupBy(v => v)
        .ToDictionary(g => g.Key, g => g.Count());
    
    foreach(var kvp in result)
    {
        Console.WriteLine("{0} appears {1} time(s)", kvp.Key, kvp.Value);
    }

DotNetFiddle.Net

Result:

-1.7 appears 2 time(s)

3.0 appears 1 time(s)

0.0 appears 2 time(s)

1.5 appears 1 time(s)

2.3 appears 1 time(s)

-1 appears 1 time(s)

7 appears 1 time(s)

Community
  • 1
  • 1
Erik Philips
  • 53,428
  • 11
  • 128
  • 150
  • But -1.7 appears 3 times not 2. And -1 and 7 are not in the list at all. – Kevin Apr 21 '17 at 19:22
  • Excuse me, there might be a mistake regarding your decimals... Some of them are -1.7, and other are -1,7 turning -1 and 7 into two separate numbers. But thank you! – Rune Hobbo Apr 21 '17 at 19:23
  • I see why, the last entry is -1,7 not -1.7. Looks like the code is good, he just messed up the results by mistyping the source array. – Kevin Apr 21 '17 at 19:23
  • I wanted to avoid using Linq, because my teacher doesn't want us to use it yet... But I think it's unavoidable. Thank you! – Rune Hobbo Apr 21 '17 at 19:27
  • 1
    @RuneHobbo It is very avoidable and you should probably listen to what your teacher tells you. – I.B Apr 21 '17 at 19:28
  • @CNuts Then, how can I make this code works without using Linq? – Rune Hobbo Apr 21 '17 at 19:29
  • @RuneHobbo You almost had it all you needed to add was to not print the same values twice. – I.B Apr 21 '17 at 19:30
  • @CNuts Yes, I know that. But how can I tell the program to not print the same values twice? – Rune Hobbo Apr 21 '17 at 19:32
  • @RuneHobbo You could put each value you print in a list and then each time you wanna print a new value you verify if it doesn't exist in that list. – I.B Apr 21 '17 at 19:33
3

Try to use Dictionary instead. Here is the code:

    var arr = new double [] { -1.7, 3.0, 0.0, 1.5, 0.0, -1.7, 2.3, -1.7 };
    var dic = new Dictionary<double, int>();

    foreach (var element in arr)
    {
        if (dic.ContainsKey(element))
            dic[element]++;
        else
            dic[element] = 1;
    }

    foreach (var element in dic)
    {
        Console.WriteLine(element.Key + " appears " + element.Value + " time(s)");
    }
Mhd
  • 2,778
  • 5
  • 22
  • 59
1

Nononononono. You are not using the power and functionality of C#. This might as well be a c++ program. A better way is to convert your array to lists using something like

List<float> list=vet.ToList()

then you can follow the information here: Get a list of distinct items and their count

and I will write it here:

var query = list.SelectMany(x => x.Names)
            .GroupBy(s => s)
            .Select(g => new { Name = g.Key, Count = g.Count() });

foreach(var result in query) {
    Console.WriteLine("Name: {0}, Count: {1}", result.Name, result.Count);
}
Community
  • 1
  • 1
Seth Kitchen
  • 1,526
  • 19
  • 53
  • Sorry! I am still a student, beginner also. I don't know at all about Linq, but this answer helped a lot, thanks! – Rune Hobbo Apr 21 '17 at 19:25
1

Typical solution is based on Linq:

using System.Linq;

...

var freqs = vet
  .GroupBy(item => item)
  .OrderBy(chunk => chunk.Key)
  .Select(chunk => 
     $"{chunk.Key,4:f1} appears {chunk.Count()} {(chunk.Count() > 1 ? "times" : "time")}");

Console.WriteLine("The number of times each element appears in the array is:");

Console.Write(string.Join(Environment.NewLine, freqs));

Console.ReadKey();

Outcome:

The number of times each element appears in the array is:
-1.7 appears 3 times
 0.0 appears 2 times
 1.5 appears 1 time
 2.3 appears 1 time
 3.0 appears 1 time
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215