Home > Back-end >  How to remove duplicate numbers (int) in C#
How to remove duplicate numbers (int) in C#

Time:02-26

How to remove duplicated in a listbox using for loop. I have tried few methods but they are not working. I've tried a last method but instead of removing the duplicates, they are replaced with 0.

My assignment is about generating a random numbers in a listbox and separating to even and odd numbers in a separate listbox. Then i have to calculate the average and selected numbers into cube and sqroot. Everything is working fine. Except the duplicates. Need some help.

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AssignmentQ1
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnGenerate_Click(object sender, EventArgs e)
        {


            List<int> lstRN = new List<int>();

            Random rnd = new Random();
            int numbers = rnd.Next(1, 1000);

            int item = 0;
            int digit = 0;
            int totalOdd, totalEven, countEven, countOdd;
            totalOdd = totalEven = countEven = countOdd = 0;
            double avg = 0.0;
            double sum = 0.0;

           

            for (int i=0; i<numbers; i  )
            {
                item = rnd.Next(1, 300);
                lstRN.Add(item);
                
            }

            lstRN.Sort();


            digit = lstRN[0];

            for (int k= 0; k<lstRN.Count; k  )
            {
                if(lstRN[k] == digit)
                {
                    lstRN[k]=0;

                }
                else
                {
                    digit = lstRN[k];
                }

            }



            foreach (int num in lstRN)
            {
                if(num % 2 == 0)
                {
                    lstEven.Items.Add(num);
                    totalEven  = num;
                    
                }
                else
                {
                    lstOdd.Items.Add(num);
                    totalOdd  = num;
                   
                }

            }

           




            /**var _items1 = this.lstRN.Items.Cast<string>().Distinct().ToList();
            this.lstRN.Items.Clear();
            foreach (var item1 in _items1)
            {
                this.lstEven.Items.Add(item1);
            }

            var _items2 = this.lstRN.Items.Cast<string>().Distinct().ToList();
            this.lstRN.Items.Clear();
            foreach (var item2 in _items2)
            {
                this.lstOdd.Items.Add(item2);
            }**/


            countEven = lstEven.Items.Count;
            lblCountEven.Text = countEven.ToString();
            avg = item / countEven;
            lblAverageEven.Text = avg.ToString();

            countOdd = lstOdd.Items.Count;
            lblCountOdd.Text = countOdd.ToString();
            avg = item / countOdd;
            lblAverageOdd.Text = avg.ToString();



        }

        private void lstEven_SelectedIndexChanged(object sender, EventArgs e)
        {
            string chosen = lstEven.SelectedItem.ToString();
            int c = int.Parse(chosen);
            double sr = Math.Sqrt(c);
            lblSquare.Text = sr.ToString();

        }

        private void lstOdd_SelectedIndexChanged(object sender, EventArgs e)
        {
            string chosen = lstOdd.SelectedItem.ToString();
            int c = int.Parse(chosen);
            double cube = Math.Pow(c, 3);
            lblCube.Text = cube.ToString();
        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }
    }
}

CodePudding user response:

If you are a LINQ addict, you can use the following extension method

public static IEnumerable<T> RemoveDuplicates<T>(this IEnumerable<T> source)
{
    return source.GroupBy(x => x).Select(y => y.First());
}

It will collect all the items that are the equals and select the first of them

CodePudding user response:

There are dedicated tool/type for that - HashSet<int>.

var uniqueNumbers = numbers.ToHashSet();

To gather unique random numbers in the collection

var randomNumbers = new HashSet<int>();
while (randomNumbers.Count < numbers)
{
    var number = rnd.Next(1, 300);
    randomNumbers.Add(number)
}

.Add method will add given value only if value is not in the set yet.
HashSet.Add(T) Method

CodePudding user response:

I've tried a last method but instead of removing the duplicates, they are replaced with 0.

Well, that's what your code is doing, you are replacing the duplicates with 0, since you sort the list first and then check if the current int is same as the last one:

for (int k = 0; k < lstRN.Count; k  )
{
    if (lstRN[k] == digit)
    {
        lstRN[k] = 0; // HERE
    }
    else
    {
        digit = lstRN[k];
    }
}

So instead you could do following:

  • while generating the random numbers use a HashSet<int> and check if it already contains the new one(HashSet.Add returns a bool). If so repeat it, so use a loop for it
  • use HashSet.ToList to create your final result

You can also use this approach with a List<int> and a Contains check, but it's less efficient.

However, in your use case this will NOT work. You are generating random numbers between 1 and 299: rnd.Next(1, 300)

But the list should get 1000 numbers, so you can't generate unique numbers anymore after 299.

So you need a different approach:

  • don't use rnd.Next(1, 300) but for example rnd.Next(1, 1000)(will be slow)
  • don't generate the numbers but generate a random sort:

// generate a consecutive list of numbers, then sort it randomly
lstRN = Enumerable.Range(1, 299)
    .Select(i => i)
    .OrderBy(i => rnd.Next(1, 300))
    .ToList();
  • Related