Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C#: how to detect repeating values in an array and process them in such a way that each repeating value is only processed once?

Tags:

c#

for-loop

I wrote this simple program:

    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("Number of elements in the array: ");
            int numberOfElements = int.Parse(Console.ReadLine());
            int[] array = new int[numberOfElements];
            for(int i = 0; i < numberOfElements; i++)
            {
                Console.Write($"Element no {i+1}: ");
                array[i] = int.Parse(Console.ReadLine());
            }
            for(int i = 0; i < array.Length; i++)
            {
                int count = 0;
                for(int j = 0; j < array.Length; j++)
                {
                    if(array[i] == array[j])
                    {
                        count++;
                    }
                }
                Console.WriteLine($"{array[i]} appears " + count + " times");
            }
        }
    }
}

Is there any option to make the displayed values print only once? For example, if there are three occurrences - the message displays three times. Is it possible to make it display once when there are more occurrences though?

like image 265
Sigma Avatar asked Oct 02 '20 07:10

Sigma


3 Answers

The first idea I had was the same of the comment from Jon Skeet, since the simplicity it implies.

The idea is to set null for the value we have already counted (matched).

From a developer point of view it is very simple and doesn't deviate too much from the OP's code.

        Console.Write("Number of elements in the array: ");
        int numberOfElements = int.Parse(Console.ReadLine());
        int?[] array = new int?[numberOfElements];
        for (int i = 0; i < numberOfElements; i++)
        {
            Console.Write($"Element no {i + 1}: ");
            array[i] = int.Parse(Console.ReadLine());
        }

        for (int i = 0; i < array.Length; i++)
        {
            int count = 0;
            int? current = array[i];

            if (array[i] != null)
            {
                for (int j = 0; j < array.Length; j++)
                {
                    if (current == array[j])
                    {
                        count++;
                        array[j] = null;
                    }
                }
                Console.WriteLine($"{current} appears " + count + " times");
            }
        }

int?[] defines a nullable value type. Therefore each item in the array can have either a null or int value - documentation here.

like image 28
Alex Leo Avatar answered Oct 22 '22 12:10

Alex Leo


You could use a GroupBy instead of the for loop

Groups the elements of a sequence.

var results = array
     .GroupBy(x => x)
     .Select(x => new {Value = x, Count = x.Count()});

foreach(var g in results)
   Console.WriteLine($"{g.Value} appears {g.Count} times");

Or another way it to use a HashSet to keep track of what you have displayed. A HashSet is basically a collection that contains no duplicate elements. The Add methods returns true if it can add an element or false otherwise

HashSet<T>.Add(T) Method

returns true if the element is added to the HashSet object; false if the element is already present.

var hashSet = new HashSet<int>();
for (int i = 0; i < array.Length; i++)
{
    int count = 0;
    for (int j = 0; j < array.Length; j++)
        if (array[i] == array[j])
            count++;

    // Add to the hashset, if the add method returns true, 
    // it means the value was uniquely added, ergo you have not displayed yet
    if (hashSet.Add(array[i]))
        Console.WriteLine($"{array[i]} appears " + count + " times");
}

Full Demo Here


Or another approach is to use a Dictionary. The premise is to iterate over the array, try an add each item to the dictionary with TryAdd if it's already found increment the value

var dictionary = new Dictionary<int,int>();
foreach(var item in array)
    if(!dictionary.TryAdd(item,1))
        dictionary[item]++;
    
foreach(var item in dictionary)
    Console.WriteLine($"{item.Key} appears {item.Value} times");

Full Demo Here

like image 71
TheGeneral Avatar answered Oct 22 '22 10:10

TheGeneral


An approach using Dictionary with O(n) complexity.

Console.Write("Number of elements in the array: ");

int numberOfElements = int.Parse(Console.ReadLine());
var dictionary = new Dictionary<int, int>();

for (int i = 0; i < numberOfElements; i++)
{
    Console.Write($"Element no {i + 1}: ");
    var value = int.Parse(Console.ReadLine());
    if (!dictionary.ContainsKey(value)) dictionary.Add(value, 0);

    dictionary[value] = dictionary[value] + 1;
}

foreach (var item in dictionary)
{
    Console.WriteLine($"{item.Key} appears {item.Value} times");
}
like image 32
Vimal CK Avatar answered Oct 22 '22 11:10

Vimal CK