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 abool
). 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 examplernd.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();