Deleting Duplicates From An Array - c#

I have a code where I load up a text file and save it as an array. The array contains a list of numbers with some of the numbers being duplicated. In my code I first loop through the array and replace all duplicated numbers with a -1. Then I plan on deleting all the -1 values from my array. The remaining array values (non duplicates) are then copied on to a new array to be outputted.
However I keep getting an error when I attempt to delete the -1 values from my array (see code below). I don't know why this is happening so if anyone knows anything please let me know!
P.S. This is school project so I can only use loops and if statements, not things like LINQ or foreach, etc.
public partial class Form1 : Form
{
//Global Variable
int[] Original;
public Form1()
{
InitializeComponent();
}
//Exit Application
private void mnuExit_Click_1(object sender, EventArgs e)
{
this.Close();
}
//Load File
private void mnuLoad_Click_1(object sender, EventArgs e)
{
//Code to Load the Numbers From a File
OpenFileDialog fd = new OpenFileDialog();
//Open the File Dialog and Check If A File Was Selected
if (fd.ShowDialog() == DialogResult.OK)
{
//Open File to Read
StreamReader sr = new StreamReader(fd.OpenFile());
int Records = int.Parse(sr.ReadLine());
//Assign Array Sizes
Original = new int[Records];
//Go Through Text File
for (int i = 0; i < Records; i++)
{
Original[i] = int.Parse(sr.ReadLine());
}
}
}
private void btnOutput_Click(object sender, EventArgs e)
{
//Store Original Array
string Output = "Original \n";
//Output Original Array
for (int i = 0; i < Original.Length; i++)
{
Output = Output + Original[i] + "\n";
}
//Create TempArray
int[] TempArray = new int[Original.Length];
//Set TempArray Equal to Original Array
for (int i = 0; i < Original.Length; i++)
{
TempArray[i] = Original[i];
}
//Duplicate Number Counter
int Counter = 0;
//Loop Through Entire Array
for (int i = 0; i < TempArray.Length; i++)
{
for (int j = i + 1; j < TempArray.Length; j++)
{
//Replace Duplicate Values With '-1'
if (TempArray[i] == TempArray[j])
{
TempArray[j] = -1;
Counter++;
}
}
}
//Set Size of Original Array
Original = new int[Original.Length - Counter];
//Remove -1 Values
//Index Counter
int Index = 0;
//error starts
for (int i = 0; i < TempArray.Length; i++)
{
if (TempArray[i] != -1)
{
Original[Index] = TempArray[i];
Index++;
}
}
//error ends
//Final Output -- The New Array
Output = Output + "Original Without Duplicates\n";
for (int i = 0; i < Original.Length; i++)
{
Output = Output + Original[i] + "\n";
}
lblOutput.Text = Output;
}
}
}

Reverse the line TempArray[i] = Original[Index]; to Original[Index] = TempArray[i];

The only thing you need to do in this case would be
Original = new int[Original.Length - (Counter-1)];
and yes you need to change the code to assign the values to Original instead of TempArray.
//error starts
for (int i = 0; i < TempArray.Length; i++)
{
if (TempArray[i] != -1)
{
Original[Index] = TempArray[i];
Index++;
}
}
//error ends

Let's say you have three 3's in your array. In the outer loop when you iterate and come across a 3, you set the other two 3's to -1. Now you come across the first -1 which earlier was a 3 and you have already set the last 3 to -1. Now you search for duplicates and wrongly calculate your number of duplicates in the Duplicate Number Counter (called Counter) because for you -1 is a duplicate of -1.
So, what you can do is this:
First only set all duplicates to -1 and then count the number of -1's by looping through the array again. This way you will set correctly the size of non-duplicated array elements.
To set all dups to -1:
for (int outerIndex = 0; outerIndex < Original.Length; outerIndex++)
{
var currentElement = Original[outerIndex];
for (int innerIndex = outerIndex + 1; innerIndex < Original.Length; innerIndex++)
{
if (Original[innerIndex] == currentElement) Original[innerIndex] = -1;
}
}
To get the count of non-repeating elements now:
var counter = 0;
for (int index = 0; index < Original.Length; index++)
{
if (Original[index] != -1) counter++;
}
Creating non-duplicated elements' array:
var newArrayIndex = 0;
var newArray = new int[Original.Length - counter]; //Calculated counter above
for(int i = 0; i < Original.Length; i++)
{
if (Original[i] != -1) newArray[newArrayIndex++] = Original[i];
}
//Finally, not good programming practice, but
//you can set Original to this newArray if you like...
Original = newArray;

Related

replace last character with first character for each line in textbox using multithreading

i have 3 textbox and two button,the first textbox is to specifies (n) number of lines and character in each line,the first button will randomly generate (n) number of lines inside the second textbox,the second button will read the lines from the second textbox and then replace the last character of each line with the first character.my question is that i need to know how to do this process with using multithread(depending on the Environment.ProcessorCount)
this is my code so far:
public partial class Form1 : Form
{
static int processorCount = Environment.ProcessorCount;
Thread[] arrThr = new Thread[processorCount];
static char[][] array;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int size = Convert.ToUInt16(textBox1.Text);
textBox2.Text = null;
textBox3.Text = null;
Random random = new Random(Convert.ToInt16(DateTime.Now.Second));
array = new char[size][];
for (int i = 0; i < array.Length; i++)
{
array[i] = new char[size];
for (int j = 0; j < array[i].Length; j++)
{
array[i][j] = (char)random.Next(33, 122);
textBox2.Text += Convert.ToString(array[i][j]);
}
textBox2.Text += "\r\n";
}
}
private void button3_Click(object sender, EventArgs e)
{
var lines = new List<string>(textBox2.Lines);
for (int i = 0; i < lines.Count - 1; i++)
{
lines[i] = lines[i].Replace(lines[i].ToCharArray().Last(), lines[i].ToCharArray().First());
}
textBox3.Lines = lines.ToArray();
}
}
To begin, I think the code you posted doesn't work as expected, because the Replace method will replace all instances of one character with another one (not just the last one), so if there are other characters that match the last one in the string, then they will also be replaced.
To fix this, the code could be written something like:
for (int i = 0; i < lines.Count - 1; i++)
{
lines[i] = lines[i].Substring(0, lines[i].Length - 1) + lines[i].First();
}
To run this code in parallel, the .NET framework has the Parallel.For loop which can be leveraged:
Parallel.For(0, lines.Count - 1, i =>
{
lines[i] = lines[i].Substring(0, lines[i].Length - 1) + lines[i].First();
});

Delete Element from Array Using For Loop + If Statement - C#

I Have an array, TempArray[] = {1,3,-1,5,7,-1,4,10,9,-1}
I want to remove every single -1 from this array and copy the remaining arrays into a new array called Original, which should output the numbers as 1,3,5,7,4,10,9
I can only use an if statement within a for loop!
This is what I have so far, but I keep getting an error message, System.IndexOutOfRangeException
for (int i = 0; i < TempArray.Length; i++)
{
if (TempArray[i] != -1)
{
//error occurs at this line
//My attempt is to set the new array, Original[i] equal to TempArray[i] only where the values are not -1.
TempArray[i] = Original[i];
}
}
If you can only use If statement in for loop. This looks like a school project. First you count how many non negative numbers are there in your array. Create new array with that length and fill that array.
int[] TempArray = new int[] {1,3,-1,5,7,-1,4,10,9,-1};
int[] Original ;
int countNonNegative=0;
for (int i = 0; i < TempArray.Length; i++)
{
if (TempArray[i] != -1)
{
countNonNegative++;
}
}
Original = new int[countNonNegative];
int index=0;
for (int i = 0; i < TempArray.Length; i++)
{
if (TempArray[i] != -1)
{
Original[index] = TempArray[i];
index++;
}
}
Console.WriteLine("Original Length = "+Original.Length);
using System.Linq;
int[] withoutNegativeOnes = myArray
.Where(a => a != -1)
.ToArray();
var Original = new int[TempArray.Length];
var originalCounter = 0;
for (int i = 0; i < TempArray.Length; i++)
{
if (TempArray[i] != -1)
{
Original[originalCounter++] = TempArray[i];
}
}
Now Original may contain empty spaces at the end though, but you have all the elements which aren't -1. You can use the following code to iterate through the values:
for (int i = 0; i < originalCounter; i++)
{
Console.WriteLine(Original[i]);
}
and that's because the originalCounter has the last index values that wasn't filled from TempArray's iteration.
try this one
int[] TempArray = { 1, 3, -1, 5, 7, -1, 4, 10, 9, -1 };
int[] original = TempArray.Where(i => i != -1).ToArray();
foreach(int i in original)
Console.WriteLine(i.ToString());

indexOutofRange BubbleSort when using inputbox

Its been bugging me for hours because it is always returning 0 at numbers[i] and I cant figure out the problem. code worked for a different program but I had to change it so it could have a custom array size and that's when everything went wrong.
any help would be great.
Thanks in advance.
int[] numbers = new int[Convert.ToInt16(TxtArray.Text)];
int j = 0;
for (j = numbers.Length; j >= 0; j--)
{
int i = 0;
for (i = 0; i <= j - 1; i++)
{
string NumbersInput = Microsoft.VisualBasic.Interaction.InputBox("Enter Numbers to be sorted",
"Numbers Input", "", -1, -1);
numbers[i] = Convert.ToInt16(NumbersInput);
//returns 0 in if statement
if (numbers[i] < numbers[i + 1])
{
int intTemp = 0;
intTemp = numbers[i];
numbers[i] = numbers[i + 1];
numbers[i + 1] = intTemp;
}
}
}
for (int i = 0; i < numbers.Length; i++)
{
LstNumbers.Items.Add(numbers[i]);
}
private void button1_Click(object sender, EventArgs e)
{
int sizeOfArrayInt = Convert.ToInt32(arraySize.Text);
int[] array = new int[sizeOfArrayInt];
string numbers = arrayValues.Text;
string[] numbersSplit = numbers.Split(',');
int count = 0;
foreach (string character in numbersSplit)
{
int value;
bool parse = Int32.TryParse(character, out value);
if (value != null)
{
array[count] = value;
}
count++;
}
array = this.SortArray(array);
foreach (int item in array)
{
this.listBox.Items.Add(item);
}
}
private int[] SortArray(int[] arrayToSort)
{
//int[] sortedArray = new int[arrayToSort.Length];
int count = arrayToSort.Length;
for (int j = count; j >= 0; j--)
{
int i = 0;
for (i = 0; i <= j - 2; i++)
{
if (arrayToSort[i] < arrayToSort[i + 1])
{
int intTemp = 0;
intTemp = arrayToSort[i];
arrayToSort[i] = arrayToSort[i + 1];
arrayToSort[i + 1] = intTemp;
}
}
}
return arrayToSort;
}
strong text
This I got to work as a Windows Form and the output displays in the list box as each array item or individual i iteration over the array. Of course there is no error checking. Hope that helps.
Setting aside the strangeness of how you are working with text boxes, your problem with throwing an exception would happen even without them because it lies here, in your inner loop:
for (i = 0; i <= j - 1; i++)
Suppose that numbers.Length == 2. This means that j == 2. So on the first time through the outer loop, you hit the inner loop with these conditions. The first time through, i == 0. You get to the if statement:
if (numbers[i] < numbers[i + 1])
numbers[0] exists, and numbers[1] exists, so this iteration goes through fine and i is incremented.
Now i == 1. Now the loop checks its boundary condition. i <= j - 1 == true, so the loop continues. Now when you hit that if statement, it tries to access numbers[i + 1], i.e., numbers[2], which does not exist, throwing an IndexOutOfRangeException.
Edit: Came back and realized that I left out the solution (to the exception, anyway). For the bubble sort to work, your inner loop's boundary condition should be i <= j - 2, because j's initial value is == numbers.Length, which is not zero-based, while array indexes are.
Second Edit: Note that just using a List won't actually solve this problem. You have to use the right boundary condition. Trying to access list[list.Count()] will throw an ArgumentOutOfRangeException. Just because a List will dynamically resize doesn't mean that it will somehow let you access items that don't exist. You should always take time to check your boundary conditions, no matter what data structure you use.

C# populate array with unique ints No Linq or ArrayLists;

This code is buggy but can't figure out why ... want to populate an array with 7 unique random integers without using arraylists or linq! I know the logic is not okay...
class Program
{
static void Main(string[] args)
{ int current;
int[] numbers = new int[7]; // size of that array
Random rNumber = new Random();
current = rNumber.Next(1, 50);
numbers[0] = current;
Console.WriteLine("current number is {0}", current);
for (int i=1;i<7;i++)
{
current = rNumber.Next(1, 50);
for (int j = 0; j < numbers.Length; j++)
{
do
{
if (current == numbers[j])
{
Console.WriteLine("Duplicate Found");
current = rNumber.Next(1, 50);
}
else
{
numbers[j++] = current;
break;
}
}while (current == numbers[j]);
}//inner for
}//outer for
for (int l = 0; l < 7; l++) // DISPLAY NUMBERS
{
Console.WriteLine(numbers[l]);
}
}// main
}//class
want to populate an array with 7 unique integers without using
arraylists or linq!
int[] list = new int[7];
for (int i = 0; i < list.Length; i++)
{
list[i] = i;
}
EDIT
I changed your inner loop, if the random number is already in the array; create a new random and reset j to 0.
for (int i = 1; i < 7; i++)
{
current = rNumber.Next(1, 50);
for (int j = 0; j < numbers.Length; j++)
{
if (current == numbers[j])
{
Console.WriteLine("Duplicate Found");
current = rNumber.Next(1, 50);
j = 0; // reset the index iterator
}
}//inner for
numbers[i] = current; // Store the unique random integer
}//outer for
I presume you are looking for random numbers, so the other answer is not what you are looking for.
There are a couple of issues here.
The inner loop is testing for duplicates. However, it is looking from 0 through the end of the array since it is using numbers.length. This should probably be i, to compare with already set values. numbers.length is always 7 regardless of whether or not you set any of the elements.
the assignment is using j, so presuming the first element is not a duplicate, it will be overwritten each time. That should be numbers[i] = current;. No ++ necessary as the for is handling the incrementing.
if you determine that a number is a duplicate, j should be reset to zer to check against the entire list again rather than having the while in the middle.
Without a complete rewrite, the changes will look something like this:
for (int i=1;i<7;i++)
{
current = rNumber.Next(1, 50);
for (int j = 0; j < i; j++) //----------------- loop through set values
{
if (current == numbers[j])
{
Console.WriteLine("Duplicate Found");
current = rNumber.Next(1, 50);
j = 0; // -----------------------reset the counter to start over
}
}//inner for
// if we got here there is no duplicate --------------------------------
numbers[i] = current;
}//outer for
(Please note that I have not tested this code, just added the changes)
you keep overwriting the same indexes in the else, and also checking too many indices causing the first to show up as a duplicate at all times which was false...
change it to:
for (int i=1;i<7;i++)
{
current = rNumber.Next(1, 50);
for (int j = 0; j < i; j++) ///< change to j < i. no need to check the others
{
do
{
if (current == numbers[j])
{
Console.WriteLine("Duplicate Found");
current = rNumber.Next(1, 50);
}
else
{
numbers[i] = current; ///< not j++ but i to prevent writing at the same locations over and over again
break;
}
}while (current == numbers[j]);
}//inner for
}//outer for
What about this?
int[] list = new int[7];
var rn = new Random(Environment.TickCount);
for (int i = 0; i < 7; i++)
{
var next = rn.Next(1, 50);
while(Contains(list, next))
{
next = rn.Next(1, 50);
}
list[i] = next;
}
private bool Contains(IEnumerable<int> ints, int num)
{
foreach(var i in ints)
{
if(i = num) return true;
}
return false;
}

Problem with QuickSort algorithm in C#

i wrote i quicksort algorithm in c# but it has a problem,when i compile it,it doesnt work in some conditions for example when i enter number 12,32,11 in textbox6 to sort, it gives out of range error when i go to trace it, debugger shows that num[] took nums[0]=12,nums[1]=11,nums[2]=1
Edited:
i changed the while condition and it know doesnt give out of range error but when the input is 12,32,11 output 11,12,1
private void button5_Click(object sender, EventArgs e)
{
string[] x = textBox6.Text.Split(',');
int[] nums = new int[x.Length];
for (int counter = 0; counter < x.Length; counter++)
{
nums[counter] = Convert.ToInt32(x[counter]);
}
int i = 0;
int j = nums.Length;
int pivot = nums[0];
do
{
do
{
i++;
}
while ((i < nums.Length) && (nums[i] < pivot));
do
{
j--;
}
while (nums[j]>pivot);
if (i < j)
{
int temp = i;
nums[i] = nums[j];
nums[j] = temp;
}
}while(i<j);
int temp1 = nums[0];
nums[0] = nums[j];
nums[j] = temp1;
int pivotpoint = j;
string QuickSort = "";
foreach (var n in nums)
QuickSort += n.ToString() + ",";
textBox5.Text = QuickSort;
}
Your issue is that i isn't being bounds-checked in your do-while loop. i will get incremented beyond the end of your nums array. Try modifying the while condition thus:
while ((i<nums.Length) && (nums[i]<pivot))
Of course you could simply use Array.Sort(nums);

Categories

Resources