This seems like a bug in studio or compilator - c#

Problem is that after Randomize func, array forcombo equals random_for_combo, but I do not equate them anywhere. Please help.
private void button1_Click(object sender, EventArgs e)
{
string sub = "1#2#3#4#5#6#7#8#9#10";
string[] split = sub.Split('#');
string[] forcombo = new string[split.Length / 2];
int s = 0;
for (int j = 1; j <= split.Length - 1; j += 2)
{
forcombo[s] = split[j];
s++;
}
string[] random_for_combo = new string[forcombo.Length];
random_for_combo = forcombo;
MessageBox.Show(forcombo[0] + forcombo[1] + forcombo[2] + forcombo[3] + forcombo[4], "Before random");
random_for_combo = RandomizeStrings(random_for_combo);
MessageBox.Show(forcombo[0]+forcombo[1]+forcombo[2]+forcombo[3]+forcombo[4], "After random");
}
public static string[] RandomizeStrings(string[] arr)
{
ArrayList l1 = new ArrayList(arr.Length);
ArrayList l2 = new ArrayList(arr.Length);
foreach (object k in arr)
{
l1.Add(k.ToString());
}
while (l1.Count > 0)
{
Random rnd = new Random();
int rand = rnd.Next(l1.Count);
l2.Add(l1[rand]);
l1.RemoveAt(rand);
Thread.Sleep(rnd.Next(50));
}
for (int i = 0; i < l2.Count; i++)
{
arr[i] = l2[i].ToString();
}
return arr;
}
Some helpless info to complete question..

There's a couple of problems with this code:
You're copying the reference from one array variable into another:
random_for_combo = forcombo;
This does not make the two variables contain two arrays that contain the same values, the two values now refer to the same one array in memory. Change one, and it will appear the other one changed as well. Think of the two variables as postit notes with the address of a house on them, the same address. If you go to the house and rearrange the furniture, "both houses" will appear to be changed. There is only one house however.
When you pass the array to the randomize method, you're passing a reference to the array, not a copy of the array, which means that if you change the contents of the array, you're not working on a copy, you're working on the original. This means that the array you get passed, and the array you return, is the same one array in memory
Probably not the source of the bugs in your question, but you shouldn't construct new Random objects every time you use it in a loop, instead construct it once and reuse, otherwise you risk getting back just a few distinct values.
Lastly, if your gut reaction is "this is a bug in visual studio or C#", then it almost never is, always work on the presumption that it is your own code that is faulty. By "almost never" I would say that the chance of you hitting a bug in C# or Visual Studio by chance is none.
To make a new array with the same contents of another, you have a few options:
Explicitly make an array and copy over the elements one by one:
random_for_combo = new string[forcombo.Length];
for (int i = 0; i < forcombo.Length; i++)
random_for_combo[i] = forcombo[i];
Use Array.Copy instead of the for-loop:
random_for_combo = new string[forcombo.Length];
Array.Copy(forcombo, random_for_combo, forcombo.Length);
Use the new Linq ToArray extension method:
random_for_combo = forcombo.ToArray();
Note that even though this looks like a no-op (since forcombo is an array), you'll actually get a new array with the same contents.

but you did here :
random_for_combo = forcombo;
you set random_for_combo so it point to forcombo.
if you want to use the original array than you need to copy it to new array
something like this (instead of the above line)
string[] random_for_combo = new string[forcombo.Length];
for (int i = 0; i < forcombo.Length; i++)
{
random_for_combo[i] = forcombo[i];
}

Related

Is there a way to add a number of elements to the array in C#?

I'm learning C# and I have created a code to add random numbers to a List using a for loop.
class Program
{
static void Main(string[] args)
{
Random numberGen = new Random();
List<int> randomNum = new List<int>();
for (int i = 0; i < 10; i++)
{
randomNum.Add(numberGen.Next(1, 100));
}
for (int i = 0; i < randomNum.Count; i++)
{
Console.WriteLine(randomNum[i]);
}
Console.ReadKey();
}
}
I want to know if there is a way to add random numbers to an array with a similar method?
The size of an array is fixed at the time of creation, so you can't add to an array; you can, however: create a new array that is bigger, copy the old data, and then append the new value(s) - Array.Resize does the first two steps - but: this is pretty expensive, which is why you usually use a List<T> or similar for this scenario. A List<T> maintains an oversized array in the background, so that it only has to resize and copy the underlying array occasionally (essentially, it doubles the size every time it gets full, so you get something approximating O(Log2(N)) overhead due to growth).
You could just assign to the relevant index directly, but note you'll have to initialize the array to the required size (as opposed to a List that can grow dynamically):
int[] randomNum = new int[10];
for (int i = 0; i < randomNum.Length; i++)
{
randomNum[i] = numberGen.Next(1, 100);
}
Use a List<T>, thats is the scenario it was precisely designed for. Once you've finished adding elements to it, if you need an array then simply call ToArray():
var myList = new List<int>();
//add random number of random numbers
var myArray = myList.ToArray();

Check against two separate array values and grabbing the smallest one to insert into a new array the CW new array values

I am working with Arrays and conditionals statements, little lost right now and was hoping for some input.
So, I created two Arrays
int[] one = new int[] {
4160414, 6610574, 2864453, 9352227, -4750937, -3132620, 2208017,
-2226227, -8415856, -9834062, -3401569, 7581671, 8068562, 7520435,
-9277044, -7821114, -3095212, 966785, 6873349, -8441152, -7015683,
-6588326, -282013, 4051534, 9930123, -3093234 };
int[] two = new int[] {
1099626, 6083415, 8083888, -8210392, 2665304, -8710738, -8708241,
8859200, -1255323, 5604634, 2921294, -7260228, 7261646, 1137004,
5805162, 4883369, 8789460, 9769240, 319012, -7877588, -1573772,
5192333, 1185446, 1302131, 4217472, -3471445};
My next step what i was thinking is i am going to have to loop through each array
for (int i = 0; i < one.Length; i++)
{
int xValue = one[i];
for (int j = 0; j < two.Length; j++)
{
int yValue = two[j];
}
}
Now that i have the index of each Array i need to check wether the index of xValue is less than the index of yValue
if (xValue < yValue)
{
// dO SOMETHING HERE
}
if (yValue < xValue)
{
// Do Something HERE
}
Where i am getting confused at, is with C# from my understanding you can not push new values into an Array, it needs to be a new instance of the array and copy?
So i tried doing
if (xValue < yValue)
{
Array.Copy(one, x, 13);
}
if (yValue < xValue)
{
Array.Copy(two, x, 13)
}
Both Arrays have 26 values, so a new array of 13 would need to be created to insert the checked value, but Array.Copy seems to not be working getting an array out of bounds check lower bounds.
I'm just confused on checking the values of both arrays at their index, then grabbing the smallest value of the checked values then taking that small value and inserting it into a new array, then use a foreach-loop to iterate over it and print the values to the console. FacePalm
You can use LINQ's Zip to achieve this:
int[] smallest = one.Zip(two, (o, t) => Math.Min(o,t)).ToArray();
Essentially, Zip will provide both items to the lambda expression, allowing you to combine them how you see fit. In this case, we just choose the minimum and return it.
Try it online
Basically, you need to define the size of the new array when you declare it. Make it the same size as one. Then add the smallest item from one or two on each iteration by comparing the items in each array at index i.
int[] smallest = new int[one.Length];
for (int i = 0; i < one.Length; i++)
{
if (one[i] < two[i])
{
smallest[i] = one[i];
}
else
{
smallest[i] = two[i];
}
}

Enumerable.Repeat has some memory issues?

I initialized an Array as
Double[][] myarr = Enumerable.Repeat(new double[12], 13).ToArray();
Then in a loop i am incrementing values like
myarr[0][0]++;
This causes all values like myarr[1][0], myarr[2][0], myarr[3][0] ..... myarr[12][0] to increment by one.
This problem is not occurring when using a for loop (0-12) i am initializing like
myarr[i] = new double[12];
Why is this so?
Other answers have explained the problem. The solution is to create a new array on each iteration, e.g.
double[][] myarr = Enumerable.Range(0, 13)
.Select(ignored => new double[12])
.ToArray();
It's because new double[12] creates a single array object in memory - Enumerable.Repeat is simply providing you with multiple references to that array.
This is expected behavior - array is a referebce type. You are creating a jagged array i.e. array of arrays. All elements of your outer array references the same inside array i.e the first argument of Repeat call, so changes in the inside array will be reflected at on indices (because all indices refer to the same array).
With new double[12] you are creating reference to array of doubles, and then you repeate the reference 12 times, so myarr[0..n] will have reference to one memory region.
You can use the folowing method to resolve thw issue
static T[][] CreateArray<T>(int rows, int cols)
{
T[][] array = new T[rows][];
for (int i = 0; i < array.GetLength(0); i++)
array[i] = new T[cols];
return array;
}
Or with custom Repeat method which calls action every step:
public static IEnumerable<TResult> RepeatAction<TResult>(Action<TResult> elementAction, int count)
{
for (int i = 0; i < count; i++)
{
yield return elementAction();
}
yield break;
}
usage
RepeatAction(()=>new double[12], 12);
Arrays are references. In the Repeat call you create one array and assign its reference 12 times. In your loop however you create 12 distinct arrays.
Repeat() basically just capture and yields the same element multiple times, so you got multiple references to the same object instance in the memory.
This is how Repeat() is implemented:
private static IEnumerable<TResult> RepeatIterator<TResult>(TResult element, int count)
{
for (int i = 0; i < count; i++)
{
yield return element;
}
yield break;
}

C# rows of multi-dimensional arrays

In the C# programming language, how do I pass a row of a multi-dimensional array? For example, suppose I have the following:
int[,] foo;
foo = new int[6,4];
int[] least;
least = new int[6];
for(int i = 0; i < 6; i++)
{
least[i] = FindLeast(ref foo[i]); //How do I pass the ith row of foo???
}
Also, could anyone explain to me the benefit of having rectangular and jagged arrays in C#? Does this occur in other popular programming languages? (Java?)
Thanks for all the help!
You can't pass a row of a rectangular array, you have to use a jagged array (an array of arrays):
int[][] foo = new int[6][];
for(int i = 0; i < 6; i++)
foo[i] = new int[4];
int[] least = new int[6];
for(int i = 0; i < 6; i++)
least[i] = FindLeast(foo[i]);
EDIT
If you find it so annoying to use a jagged array and desperately need a rectangular one, a simple trick will save you:
int FindLeast(int[,] rectangularArray, int row)
You don't, with a rectangular array like that. It's a single object.
Instead, you'd need to use a jagged array, like this:
// Note: new int[6][4] will not compile
int[][] foo = new int[6][];
for (int i = 0; i < foo.Length; i++) {
foo[i] = new int[4];
}
Then you can pass each "sub"-array:
int[] least = new int[foo.Length];
for(int i = 0; i < 6; i++)
{
least[i] = FindLeast(foo[i]);
}
Note that there's no need to pass foo[i] by reference1, and also it's a good idea to assign local variables values at the point of declaration, when you can. (It makes your code more compact and simpler to understand.)
1 If you're not sure about this, you might want to read my article on parameter passing in C#.
Update: As Jon Skeet rightly points out, this does not provide a reference to the row, but rather creates a new copy. If your code needs to change a row, this method doesn't work. I have renamed the method to make this clear.
Update 2: If you want to be able to edit the fields, and have the changes happen to the parent array, too, you can use the wrapper I provide in this library I maed. The resulting row foo.Row(i) is not an array, but instead implements IList, so if you need to pass an array this is not a solution, either.
This extension method will allow you to query a multi-dimensional array for rows. It should be noted that this is computationally heavy (not efficient) and if it is possible you should use a jagged array for these situations. If, however, you find yourself in a situation where you cannot use a jagged array, this might be useful.
public static T[] CopyRow<T>(this T[,] arr, int row)
{
if (row > arr.GetLength(0))
throw new ArgumentOutOfRangeException("No such row in array.", "row");
var result = new T[arr.GetLength(1)];
for (int i = 0; i < result.Length; i++)
{
result[i] = arr[row, i];
}
return result;
}
Your code can now be rewritten:
int[,] foo;
foo = new int[6,4];
int[] least;
least = new int[6];
for(int i = 0; i < 6; i++)
{
least[i] = FindLeast(ref foo.CopyRow(i));
}

How to delete a chosen element in array?

I have this assignment where I must delete a chosen element from an array, so I came up with this code:
strInput = Console.ReadLine();
for (int i = 0; i < intAmount; i++)
{
if (strItems[i] == strInput)
{
strItems[i] = null;
for (int x = 0; x < intAmount-i; x++)
{
i = i + 1;
strItems[i - 1] = strItems[i];
}
intAmount = intAmount - 1;
}
}
The problem is that, suppose I have an array [1,2,3,4,5,], and I want to delete 1. The output would be [2,3,4,5,5]. This also happens when I choose 2, but it does not happen when I choose any other number.
What am I doing wrong?
I'm assuming you are working with a basic array of strings:
var strItems = new string[] { "1", "2", "3", "4", "5" };
In .NET, that array is always going to be 5 elements long. In order to remove an element, you are going to have to copy the remaining elements to a new array and return it. Setting the value at a position to null does not remove it from the array.
Now, with things like LINQ this is very easy (not shown here), or you could cheat using the List<> collection and do this:
var list = new List<string>(strItems);
list.Remove("3");
strItems = list.ToArray();
But I don't think that's going to teach you anything.
The first step is to find the index of the element you wish to remove. You can use Array.IndexOf to help you out. Let's find the middle element, "3":
int removeIndex = Array.IndexOf(strItems, "3");
If the element was not found, it will return a -1, so check for that before doing anything.
if (removeIndex >= 0)
{
// continue...
}
Finally you have to copy the elements (except the one at the index we don't want) to a new array. So, altogether, you end up with something like this (commented for explanation):
string strInput = Console.ReadLine();
string[] strItems = new string[] { "1", "2", "3", "4", "5" };
int removeIndex = Array.IndexOf(strItems, strInput);
if (removeIndex >= 0)
{
// declare and define a new array one element shorter than the old array
string[] newStrItems = new string[strItems.Length - 1];
// loop from 0 to the length of the new array, with i being the position
// in the new array, and j being the position in the old array
for (int i = 0, j = 0; i < newStrItems.Length; i++, j++)
{
// if the index equals the one we want to remove, bump
// j up by one to "skip" the value in the original array
if (i == removeIndex)
{
j++;
}
// assign the good element from the original array to the
// new array at the appropriate position
newStrItems[i] = strItems[j];
}
// overwrite the old array with the new one
strItems = newStrItems;
}
And now strItems will be the new array, minus the value specified for removal.
Arrays in C# are of a fixed size - once initialized you can only modify items, but you cannot add or remove items. If you want to delete an item from a collection you have two options:
1.) Create a new array that has all members of the original array minus the one you want to remove.
2.) Use a collection type that is resizable and allows to add or remove items like List<T> (List<int> in your case). This is what you would do in the "real world" if your collection is not static.
In your specific implementation i think u miss a break; statement, you should go out from the outer loop when you finish the inner loop. The assignment to null is not useful at all.
If the list is just a list of numbers why are you using strings? use integers directly if it is the case.
Your exercise seems to ask something like this, if you need to remove only one element.
public bool MyDelete(int[] array, int value) // Easy to do for strings too.
{
bool found = false;
for (int i = 0; i < array.Length; ++i)
{
if (found)
{
array[i - 1] = array[i];
}
else if (array[i] == value)
{
found = true;
}
}
return found;
}
This function will returns true if it find the specified falue, false if not.
It will move all items as you describe in your example, but of course, it will not change the size of the array.
Arrays are fixed size.
You cannot change the size of an array, simply, the language don't allows that.
Arrays are, were and will be always fixed size!
To remove an item from an array you should do something this:
public static T[] RemoveAt<T>(T[] array, int index) // hope there are not bugs, wrote by scratch.
{
int count = array.Length - 1;
T[] result = new T[count];
if (index > 0)
Array.Copy(array, 0, result, 0, index - 1);
if (index < size)
Array.Copy(array, index + 1, result, index, size - index);
return result;
}
...
strItems = RemoveAt(strItems, index);
This function will create a new array that contains all elements except the one at the index you specify.
Now, why someone would do something like this instead of using a List or a Dictionary or wathever?
Use directly a List without using an array.
Can use Except method to filter the data
AllData = {10, 30, 20, 50}
FilterData = {30, 20}
Result = AllData.Except(​FilterData)
Result will be {10, 50}
Arrays are a fixed sized, you can't shorten their length without creating a new array. All you can do is store the length of valid elements in the array (ie. after you remove 1 the length is 4).
Also, I'm not sure if the order of elements in your array is important, but if it's not you could swap the first and last elements rather than moving every element after the one that's removed forward 1 position.
An alternative to using an array is using a collection such as an ArrayList which will take care of resizing, removing and keeping a count of the amount of items in it, plus a lot more.
However, since this is homework you might have to use arrays. Either keep track of the length with a variable, as opposed to using array.length, or create a new array each time you want to change the size. If you don't have to use arrays then look at the collections you can use in C#.

Categories