Efficiently shrinking a two dimensional array in C# - c#

What is an efficient way to shrink a two dimensional array to a smaller size in C#?
For example:
var bigArray = new object[100, 100];
var smallArray = new object[10, 10];
bigArray[0, 0] = 1;
bigArray[0, 1] = 2;
...
bigArray[99, 99] = 100000;
startRowIndex = 0;
startColumnIndex = 0;
endRowIndex = 9;
endColumnIndex = 9;
smallArray = bigArray.SomeShirnkingMethod(startRowIndex, startColumnIndex, endRowIndex, endColumnIndex);
How will you write SomeShrinkingMethod() ?
Thanks!
EDIT: I'm simply trying to get the first 10 rows and columns of the bigArray into the smallArray but I'm not sure if a looping through the array is the most efficient method.

You've got to create a new array of the desired size (in your code, you've already done this) and copy the content. I'm not sure what the “shrinking” operation needs to do in your case. However, you cannot modify the dimensions of an existing array.
The function you proposed is defective because it can't know the dimensions of the target array. Either you pass it the dimensions and dimension the new array internally or you pass it the target array and simply copy the contents.
Edit:
In response to your edit: Yes, looping will be the reasonable way to do this and this is also reasonably fast. I'm not aware of a block-copying mechanism in .NET that can be applied to multidimensional arrays.

Depends on what you want your shrinking function to do. You've got to make a new array and do the copy based on whatever your criteria is. My assumption is that you've got a 2d array for a reason, right? The copy could either be trivia (find the next location that has a non-zero value and put it in the next available location in the target) or based on something else. Can you provide more info?

Yes the best method is almost certainly to loop over each cell, although it might be possible to copy a sequence of each 'row'. The method would need to know lower indices of the square to be copied from the source square, and the size (which might be implicit in the destination square definition).

Related

Modifying Array Length property through Reflection

So, I am stuck with one weird problem.
To give you idea what I want to achieve, but failed miserably:
int[] testArray = new int[100];
typeof(int[])
.GetProperty("Length", BindingFlags.Instance | BindingFlags.Public)
.SetValue(testArray, 50);
Yeah, that is, I want to modify C# arrays Length property (only make it less than actual size), without making new array and copying contents - to avoid GC etc etc...
Background:
In Unity, there is this function:
void SetIndices(int[] indices, MeshTopology topology, int submesh, bool calculateBounds);
As you see, SetIndices doesn't accept "start" and "end" or at least "length" as a parameter. This is why I want to modify Length of my indices array to trick this function.
Any ideas?
You can't resize an array in C#. That's the hard truth.
In fact, the Array.Resize method creates a new array and copies the values of the previous array in the new one.

In C#, Procedure that modifies incoming array by reversing it?

I've been trying to find a solution to this problem in particular.
Write a procedure that modifies the incoming array of ints by reversing it. Because this is a procedure, it will not return anything. Instead, I will have to modify the array directly, and because arrays are reference type variables, the array will be permanently changed even after this procedure. To reverse an array, imagine the array with an imaginary line in the middle of it, and then swap the numbers on the left with the numbers on the right side.
At the moment, this is the only code I've written down for the problem. Based on the code I've written so far, I don't think I'm approaching it towards the correct solution for it.
public void Test10(int[] numbers)
{
for (int i = 0; i < numbers.Length; i++)
{
}
You could use built-in Array.Reverse method, which reverses the sequence of the elements in the entire one-dimensional Array.
Array.Reverse(array); // reverse supplied array
Please note, System.Array.Reverse() does in place transformation.
There are 2 options based on your preference and need
int[] array = {1,3};
Array.Reverse(array);
This will reverse the original array
int[] array = {1,3};
var reversedArray = array.Reverse().ToArray();
This will use linq and new reversed array will be returned and original array will remain as it is

The value of a variable changes after it's line of code is run in C#?

I've met this problem a couple times befores. Here's an example code:
public void moveRight(int x, int y, int rows, int columns)
{
char[,] imatrix = GameInstance.vexedGame.getLastMatrix(); // <-- creating a variable and initializing it.
char letter = imatrix[x, y]; // Doesn't matters
char[,] oldMatrix = imatrix; // Creating a new var that is the same as the variable created before
if (imatrix[x, (y + 1)] == '-')
{
//LINE 1
GameInstance.vexedGame.setLastMatrix(oldMatrix); //Setting the var of this class to the old matrix (until here everything's fine)
imatrix[x, (y + 1)] = letter;
imatrix[x, y] = '-'; //Changing the matix
//LINE 2
GameInstance.vexedGame.setActualMatrix(imatriz); //Setting the actual matrix.
}
}
What happens is that when I put breakpoints in the whole thing, when I get to the //LINE 1, the value is saved with the copy of the matrix before the changes. After I make the changes in //LINE 2, not only the value of imatrix is changed but also the value of the first matrix changes, so the GameInstance.vexedGame.setLastMatrix changes. I don't really know why this happens, and if anybody could help me I would really appreciate it. Thanks!
(Sorry for my bad english)
That's because its an array and arrays are reference type.
When you do
char[,] oldMatrix = imatrix;
this creates a shallow copy. i.e. the address in memory is passed to oldmatrix. Now they are two variables but pointing to same adress in memory. if you change first the second obviously has to change.
To avoid this use loop to copy each value from first to second or
do a deep copy.
Ok so to expand on the other answers here. To do a deep copy you would need to either manually iterate through the values and assign them in that fashion, or use a prebuilt method. Something that could work would be Array.CopyTo(); now this comes with issues as its a one dimensional array copy but that can be worked around with some coding. A helpful slightly different helper function is Array.Copy(); which is meant for copying ranges of values.
The reason it is one dimensional is that there is no telling how jagged the data sizes are within the two dimensions. This therefore is highly dependent on the structure of that multidimensional array. So it falls on the developer to solve that problem unless you can post the structure, for assistance.

Calculating numbers from an external file from my project (Project Euler #13)

I'm trying to find multiple ways to solve Project Euler's problem #13. I've already got it solved two different ways, but what I am trying to do this time is to have my solution read from a text file that contains all of the numbers, from there it converts it and adds the column numbers farthest to the right. I also want to solve this problem in a way such that if we were to add new numbers to our list, the list can contain any amount of rows or columns, so it's length is not predefined (non array? I'm not sure if a jagged array would apply properly here since it can't be predefined).
So far I've got:
static void Main(string[] args)
{
List<int> sum = new List<int>();
string bigIntFile = #"C:\Users\Justin\Desktop\BigNumbers.txt";
string result;
StreamReader streamReader = new StreamReader(bigIntFile);
while ((result = streamReader.ReadLine()) != null)
{
for (int i = 0; i < result.Length; i++)
{
int converted = Convert.ToInt32(result.Substring(i, 1));
sum.Add(converted);
}
}
}
which reads the file and converts each character from the string to a single int. I'm trying to think how I can store that int in a collection that is like 2D array, but the collection needs to be versatile and store any # of rows / columns. Any ideas on how to store these digits other than just a basic list? Is there maybe a way I can set up a list so it's like a 2D array that is not predefined? Thanks in advance!
UPDATE: Also I don't want to use "BigInteger". That'd be a little too easy to read the line, convert the string to a BigInt, store it in a BigInt list and then sum up all the integers from there.
There is no resizable 2D collection built into the .NET framework. I'd just go with the "jagged arrays" type of data structure, just with lists:
List<List<int>>
You can also vary this pattern by using an array for each row:
List<int[]>
If you want to read the file a little simpler, here is how:
List<int[]> numbers =
File.EnumerateLines(path)
.Select(lineStr => lineStr.Select(#char => #char - '0').ToArray())
.ToList();
Far less code. You can reuse a lot of built-in stuff to do basic data transformations. That gives you less code to write and to maintain. It is more extensible and it is less prone to bugs.
If you want to select a column from this structure, do it like this:
int colIndex = ...;
int[] column = numbers.Select(row => row[index]).ToArray();
You can encapsulate this line into a helper method to remove noise from your main addition algorithm.
Note, that the efficiency of all those patterns is far less than a 2D array, but in your case it is good enough.
In this case you can simply use an 2D array, since you actually do know in advance its dimensions: 100 x 50.
If for some reason you want to solve a more general problem, you may indeed use a List of Lists, List>.
having said that, I wonder: are you actually trying to sum up all the numbers? if so, I would suggest another approach: consider just which section part of the 50 digit numbers actually influences the first digits of their sum. Hint: you don't need the entire number.

Copying part of a Multidimentional Array into a smaller one

I have two multi-dimentional arrays declared like this:
bool?[,] biggie = new bool?[500, 500];
bool?[,] small = new bool?[100, 100];
I want to copy part of the biggie one into the small. Let’s say I want from the index 100 to 199 horizontally and 100 to 199 vertically.
I have written a simple for statement that goes like this:
for(int x = 0; x < 100; x++)
{
For(int y = 0; y < 100; y++)
{
Small[x,y] = biggie[x+100,y+100];
}
}
I do this A LOT in my code, and this has proven to be a major performance jammer.
Array.Copy only copies single-dimentional arrays, and with multi-dimentional arrays it just considers as if the whole matrix is a single array, putting each row at the end of the other, which won’t allow me to cut a square in the middle of my array.
Is there a more efficient way to do this?
Ps.: I do consider refactoring my code in order not to do this at all, and doing whatever I want to do with the bigger array. Copying matrixes just can’t be painless, the point is that I have already stumbled upon this before, looked for an answer, and got none.
In my experience, there are two ways to do this efficiently:
Use unsafe code and work directly with pointers.
Convert the 2D array to a 1D array and do the necessary arithmetic when you need to access it as a 2D array.
The first approach is ugly and it uses potentially invalid assumptions since 2D arrays are not guaranteed to be laid out contiguously in memory. The upshot to the first approach is that you don't have to change your code that is already using 2D arrays. The second approach is as efficient as the first approach, doesn't make invalid assumptions, but does require updating your code.

Categories