How do I exclude the zeros from outputting in my array? - c#

I have this code. I would like to only display the parts of the array that are greater than 0.
For example... A bunch of numbers are entered and stored as a variable. But not all of the variables in the array will be used. The ones that aren't are stored as 0. So when I display the array, the numbers are displayed as:
"140, 180, 298, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, " etc.
I don't want the zeros to be displayed.
int[] scores = {score1, score2, score3, score4, score5, score6, score7, score8, score9, score10, score11, score12, score13, score14, score15};
Console.WriteLine("Your scores as you entered them: " + (string.Join(", ", scores)));
Console.ReadKey();

Use linq's Where:
string.Join(", ", scores.Where(x => x != 0))
In the description above you also said the parts of the array that are greater than 0. So if that is the case you can change it to:
string.Join(", ", scores.Where(x => x > 0))
For a non linq solution use a List<int> and a simple foreach (or for) loop:
List<int> result = new List<int>();
foreach(int item in scores)
{
if(item != 0)
result.Add(item);
}

If you don't understand LINQ yet, you can look into this piece of code:
int[] scores = { 1, 2, 3, 0, 0, 4, 5, 0, 0, 6};
int[] withoutZeros = WithoutZeros (scores);
And the core method:
public static int[] WithoutZeros (int[] input)
{
int zerosCount = 0; // we need to count how many zeros are in the input array
for (int i = 0; i < input.Length; i++)
{
if (input[i] == 0) zerosCount = zerosCount + 1;
}
// now we know number of zeros, so we can create output array
// which will be smaller than then input array (or not, if we don't have any zeros in the input array)
int[] output = new int[input.Length - zerosCount]; // can be smaller, equal, or even empty
// no we need to populate non-zero values from the input array to the output array
int indexInOutputArray = 0;
for (int i = 0; i < input.Length; i++)
{
if (input[i] != 0)
{
output[indexInOutputArray] = input[i];
indexInOutputArray = indexInOutputArray + 1;
}
}
return output;
}

To get the answer of your question have a look at Gilad Green's answer.
I just wanted to give you a little feedback about the code I see.
Since, I dont see all your code I am making a lot of assumptions here, so sorry if I am wrong.
If you want to fill an array with 15 values, you should consider refactoring your code to use a loop.
In the following example I will use a for loop but it could be solved with different loops.
int[] scores = new int[15]; //initialize an array of ints with a length of 15
for (int i = 0; i < scores.Length; i++) //loop from 0 till smaller than the length of the array (0-14 = 15 iterations)
scores[i] = int.Parse(Console.ReadLine()); //fill the scores array with the index of i with the console input

Related

is there a better way to expand array size in c#

When I run this code the array has a new size after, is there anything wrong or bad about it ?
static int[] ExpandArray(int[] input, int add_size)
{
for (int i = 0; i < add_size; i++)
{
int[] temp = input;
input = new int[input.Length + 1];
for (var j = 0; j < temp.Length; j++)
{
input[j] = temp[j];
}
}
return input;
}
static void Main(string[] args)
{
int[] ovride = new int[3] { 1, 2, 3 };
ovride = ExpandArray(ovride, 10);
ovride = ExpandArray(ovride, 10);
Console.WriteLine(ovride.Length);
}
is there anything wrong or bad about it ?
This isn't code review, but:
Yes. You should not resize arrays. This involves a new allocation and a copy of all elements. As does Array.Resize(), by the way.
Hey, there is a method that already does this: Array.Resize(). Don't reinvent the wheel.
You definitely should not do the resize in a loop.
So to clean up the code a little:
static int[] ExpandArray(int[] input, int sizeToAdd)
{
// Create a new array with the desired size
var ouput = new int[input.Length + sizeToAdd];
// Copy all elements from input to output
for (int i = 0; i < input.Length; i++)
{
output[i] = input[i];
}
// Return the new array, having the remaining
// items set to their default (0 for int)
return output;
}
You'd actually want input to be updatable by ref, and then end with input = output.
Ultimately, just use a List<int>, as that allows for more efficient resizing, and does so automatically when necessary.
You can use Array.Resize which:
Changes the number of elements of a one-dimensional array to the specified new size.
int[] ovride = new int[3] { 1, 2, 3 };
Array.Resize(ref ovride, ovride.Length + 10);
Array.Resize(ref ovride, ovride.Length + 10);
Console.WriteLine(ovride.Length); // prints 23
But if you expect collection size changes List can be a more suitable option for your goal.

is there any way to take an int turn it into a string and then into an int again

i want to get the length of a number. i know i can do it with a while loop and dividing by 10 until the number reaches 0 but that takes around 10 line of code and i'm thinking it would be much quicker and much much more efficient to do it this way.
using System;
int[] array = new int[5]{1,12,123,1234,12345};
int[] length = new int[array.Length];
int i = 0;
while (i < 0)
{
length[i] = int.Parse(((array[i]).ToString()).Length);
i++;
}
i = 0;
while (i < array.Length)
{
Console.Write("{0} ", length);
i++;
}
for some reason when i tell it to print the code length of each number instead of printing the length(1 ,2 ,3 ,4 ,5) in just prints system.int32[] 5 times
You don't have to parse .Length since Length return int; your code amended:
int[] array = new int[] {1, 12, 123, 1234, 12345};
//TODO: you may want to put a better name here, say, digitCount
// see comments below
int[] length = new int[array.Length];
for (int i = 0; i < array.Length; ++i)
length[i] = array[i].ToString().Length;
for (int i = 0; i < length.Length; ++i)
Console.Write("{0} ", length[i]);
You can query array with a help of Linq:
using System.Linq;
...
int[] array = new int[] {1, 12, 123, 1234, 12345};
int[] length = array
.Select(item => item.ToString().Length)
.ToArray();
And print length in one go with a help of Join:
Console.Write(string.Join(" ", length));
This is because length is an array, and not the actual item (which I guess you want to print). The fix is easy, replace Console.Write("{0} ", length); with Console.Write("{0} ", length[i]);
Here a few tips for your code:
I see you are using while loops to iterate over something everywhere, so let me teach you a little about another type of loop, the for loop. The for is usually used to do something x amount of times and is constructed like so:
for (int i = 0; i < length.Length; i++)
This might seem complicated but it's actually quite simple, let me explain. We can break down the for loop into 3 sections. The iterator declaration, the iterating condition, and the increment. int i = 0 is the iterator declaration, here we declare and define a variable named i which is an int with the value 0. In the next block (i < length) we declare the condition, when this condition is true we keep on going, when it is false we stop looping. And lastly is the increment or step (i++), this gets executed after every loop and increments the iterator (i in this case) by 1. Rewriting your code with for loops results in this:
int[] array = new int[] {1, 12, 123, 1234, 12345};
int[] length = new int[array.Length];
for (int i = 0; i < array.Length; i++)
{
length[i] = int.Parse(((array[i]).ToString()).Length);
}
for (int i = 0; i < length.Length; i++)
{
Console.WriteLine("{0} ", length[i]);
}
This can still further be improved, for example, currently we are iterating twice over what is essentially the same data, which means we are wasting time. And also, since arrays are enumerable in C#, we can use a foreach loop. This is another type of loop which is almost the same as the for loop, but instead of doing something x amount of times we use to to something with every element of an enumerable. Using it we can do this:
int[] array = new int[] {1, 12, 123, 1234, 12345};
foreach (int element in array)
{
Console.WriteLine($"{element.ToString().Length} ");
}
I also used something called string interpolation(the $ before the ")

How do I delete all elements in an int array that exist in another int array?

In my C# program, I have an int array containing a set of integers and occasionally duplicates of those integers. I want to create an array that only contains the numbers that exist as duplicates in the initial array, but in itself contains no duplicates. Based on my newbie understanding of C# I thought that the following code would do the trick:
int a = 9;
int b = 6;
int c = 3;
int index = 0;
int[] mltpls = new int[a + b + c];
while (a > 0)
{
mltpls[index] = 2 * a;
a -= 1;
index += 1;
}
while(b > 0)
{
mltpls[index] = 3 * b;
b -= 1;
index += 1;
}
while(c > 0)
{
mltpls[index] = 5 * c;
c -= 1;
index += 1;
}
int[] mltpls_unique = mltpls.Distinct().ToArray();
int[] mltpls_dplcts = mltpls.Except(mltpls_unique).ToArray();
Console.WriteLine(mltpls_dplcts);
//EDIT
//By running the following code I can write out all numbers in "mltpls"
for (int i = 0; i < mltpls.Length; i++)
{
Console.Write(mltpls[i] + ", ");
}
/*If I try to run equivalent code for the "mltpls_dplcts" array nothing
only a blank line is displayed.*/
When I run this goal my the final result of my console application is a blank row. My interpretation of this is that the array mltpls_dplcts is empty or that I'm incorrectly going about printing the array.
How do get only the duplicate values from an array?
My interpretation of this is that the array mltpls_dplcts is empty or that I'm incorrectly going about printing the array.
Both interpretations are correct
Distinct will return every item that is at least once present in mltps. If you now apply Except you get nothing because all items that are in mltpls_unique are also present in mltps. The items in the array are compared by value, so for Except it does not matter whether a number occurs multiple times in the other array. If it is there once it will not return the number. So you get an empty array.
Furthermore you cannot simply shove an entire array into Console.WriteLine. Either use a loop or String.Join to print the content:
Console.WriteLine(String.Join(" ",mltpls_dplcts));
Solution: You can solve it using a good old loop approach ;)
int[] mltpls_unique = mltpls.Distinct().ToArray();
// The amount of duplicates is the difference between the original and the unique array
int[] mltpls_dplcts = new int[mltpls.Length-mltpls_unique.Length];
int dupCount = 0;
for (int i = 0; i < mltpls.Length; i++)
{
for (int j = i+1; j < mltpls.Length; j++)
{
if (mltpls[i] == mltpls[j])
{
mltpls_dplcts[dupCount] = mltpls[i];
dupCount++;
}
}
}
Output: 18 12 10 6 15
You cannot print the array directly. You need to loop and print one by one:
foreach (var element in mltpls_dplcts)
{
Console.WriteLine(element);
}
You can get array of distinct duplicates like this:
var duplicates = mltpls.GroupBy(o => o)
.Where(g => g.Count() > 1)
.Select(g => g.First()).ToArray();
To get new array that contains only the elements from the original one that are not in the second array you can use:
var newArr = mltpls.Except(duplicates).ToArray();
It is not proper way to find duplicates. You can determine the duplicates by using GroupBy and print them to console like this;
var mltpls_dplcts = mltpls.GroupBy(x => x).Where(x => x.Count() > 1).Select(x => x.Key).ToArray();
foreach (var duplicate in mltpls_dplcts)
{
Console.WriteLine(duplicate);
}
Also, If it isn't must to use Array for you, I suggest you to use List<int>.
Updated question from OP:
How do get only the duplicate values from an array?
var arr1 = new[] {1, 2, 4, 4, 5, 5, 5, 5, 6, 7, 1};
var duplicates = arr1.ToLookup(_ => _, _ => _).Where(_ => _.Count()>1).Select(_ => _.Key).ToArray();
// duplicates is now { 1, 4, 5 }
Original question from OP:
How do I delete all elements in an int array that exist in another int array in C#?
var arr1 = new[] {1, 2, 4, 5, 6, 7};
var arr2 = new[] {4, 5};
var hash = new HashSet<int>(arr1);
hash.ExceptWith(arr2);
var filteredArray = hash.ToArray();
// filteredArray is now { 1, 2, 6, 7 }

Finding the closest integer value, rounded down, from a given array of integers

I am trying to figure out the best way to find the closest value, ROUNDED DOWN, in a List of integers using any n that is between two other numbers that are stored in a List. The all integers in this situation will ALWAYS be unsigned, in case that helps.
The assumptions are as follows:
The List always starts at 0
The List is always sorted ASC
All integers in the List are unsigned (no need for Math.Abs)
The number for comparison is always unsigned
For example:
List<int> numbers = new List<int>() { 0, 2000, 4000, 8000, 8500, 9101, 10010 };
int myNumber = 9000;
int theAnswer; // should be 8500
for (int i = 0; i < numbers.Count; i++) {
if (i == numbers.Count - 1) {
theAnswer = numbers[i];
break;
} else if (myNumber < numbers[i + 1]) {
theAnswer = numbers[i];
break;
}
}
The previous code example works without any flaws.
Is there a better more succint way to do it?
You can use List<T>.BinarySearch instead of enumerating elements of list in sequence.
List<int> numbers = new List<int>() { 0, 2000, 4000, 8000, 8500, 9101, 10010 };
int myNumber = 9000;
int r=numbers.BinarySearch(myNumber);
int theAnswer=numbers[r>=0?r:~r-1];
Filter list obtaining all values less than the myNumber and return last one:
theAnswer = numbers.Where(x => x <= myNumber ).Last();
A list can be indexed.
Start at the index in the middle of the list. If you found the exact number, you are good. If the number is less than the target number, search in the middle of the range from the start of the list to one less than the middle of the list. If the number is greater than the target number, work with the opposite half of the list. Continue this binary search until you find either an exact match, or the adjacent numbers that are smaller and larger than the target number.
Select the smaller of the two.
Please try this code:
List<int> numbers = new List<int>() { 0, 2000, 4000, 8000, 8500, 9101, 10010 };
int myNumber = 9000;
int theAnswer = numbers[numbers.Count - 1];
if (theAnswer > myNumber)
{
int l = 0, h = numbers.Count - 1, m;
do
{
m = (int)((double)(myNumber - numbers[l]) / (double)(numbers[h] - numbers[l]) * (h - l) + l);
if (numbers[m] > myNumber) h = m; else l = m;
}
while ((h - l) != 1);
theAnswer = numbers[l];
}

Efficient algorithm for removing an array from another array

I'm wondering if anyone knows a better (as in faster) algorithm/solution to solve my problem:
In my program I have an array of uints, from which I want to remove the entries contained in another uint array. However, I cannot use the union of the sets, because I need to keep duplicate values. Badly worded explaination, but the example should make it a bit clearer:
uint[] array_1 = new uint[7] { 1, 1, 1, 2, 3, 4, 4};
uint[] array_2 = new uint[4] { 1, 2, 3, 4 };
uint[] result = array_1 .RemoveRange(array_2);
// result should be: { 1, 1, 4 }
This is my current best idea; but it's fairly slow:
public static uint[] RemoveRange(this uint[] source_array, uint[] entries_to_remove)
{
int current_source_length = source_array.Length;
for (int i = 0; i < entries_to_remove.Length; i++)
{
for (int j = 0; j < current_source_length; j++)
{
if (entries_to_remove[i] == source_array[j])
{
// Shifts the entries in the source_array.
Buffer.BlockCopy(source_array, (j + 1)* 4 , source_array, j * 4, (current_source_length - j) * 4);
current_source_length--;
break;
}
}
}
uint[] new_array = new uint[current_source_length];
Buffer.BlockCopy(source_array, 0, new_array, 0, current_source_length * 4);
return new_array;
}
So again, can someone come up with a more clever approach to achieve what I want?
Thanks!
What about using a Dictionary<uint,int> using the uint number as the key and the number of times the number occurs as the value?
var source = new Dictionary<uint,int>();
source.Add(1,3);
source.Add(2,1);
source.Add(3,1);
source.Add(4,2);
var remove = new uint[]{ 1, 2, 3, 4 };
for (int i = 0; i<remove.Length; i++) {
int occurences;
if (source.TryGet(remove[i], out occurences)) {
if (occurences>1) {
source[remove[i]] = occurences-1;
} else {
source.Remove(remove[i]);
}
}
}
This would do what you want as far as I understand it, they key is reference counting of the number of occurrences and then using the remaining reference count (if > 0) as the number of times a number has to be emitted:
public static uint[] RemoveRange(this uint[] source_array, uint[] entries_to_remove)
{
var referenceCount = new Dictionary<uint, int>();
foreach (uint n in source_array)
{
if (!referenceCount.ContainsKey(n))
referenceCount[n] = 1;
else
referenceCount[n]++;
}
foreach (uint n in entries_to_remove)
{
if (referenceCount.ContainsKey(n))
referenceCount[n]--;
}
return referenceCount.Where(x => x.Value > 0)
.Select(x => Enumerable.Repeat(x.Key, x.Value))
.SelectMany( x => x)
.ToArray();
}
EDIT: This won't help you, since you want to keep duplicates.
I'm leaving it here for people who don't want duplicates.
Create a HashSet<T> from the second list, then call List<T>.RemoveAll with the hashset's Contains method.
var unwanted = new HashSet<uint(...);
list.RemoveAll(unwanted.Contains);
If you don't want to remove them in-place, you can use LINQ:
list.Except(unwanted);
Except will build two hashsets and return items one at a time (deferred execution0
If the arrays aren't sorted, sort them. Initialize 3 indexes to 0. 's'(source) and 'd' (dest) index the big array A, 'r' indexes the "toRemove" array B.
While r<B.length,
While B[r] > A[s], A[d++]= A[s++].
If B[r]==A[s], s++.
r++.
Endwhile.
While s<A.length, A[d++]= A[s++].
A.length = d.
This takes no extra space, and runs in O(N), (or N lg N if they are initially unsorted), compared to the N^2 I your original solution.
You can try using Linq here,
var resultarray = array1.Except(array2);

Categories