Title: Make subarray extension methods in C#
The Array class's Copy method can copy a subarray from one array to another, but it requires that you figure out how many items you want to copy. It will also copy parts of a two-dimensional array, but it only copies contiguous pieces and not rectangular chunks in the middle of the array.
This example creates two SubArray extension methods that let you copy parts of one- and two-dimensional arrays much as you can use the string class's SubString method to copy parts of a string. (I drew the red rectangles on the picture to make it easy to see which items were copied. The rectangles aren't part of the program.)
The following code shows the extension method that copies part of a one-dimensional array into a new array.
// Copy the indicated entries from an array into a new array.
public static T[] SubArray<T>(this T[] values,
int start_index, int end_index)
{
int num_items = end_index - start_index + 1;
T[] result = new T[num_items];
Array.Copy(values, start_index, result, 0, num_items);
return result;
}
The code calculates the number of items to copy and creates an array to hold that number of items. It uses Array.Copy to copy the desired subarray into the new array and returns the new array.
The following code uses this extension method to copy items 1 through 3 of a one-dimensional array into a new array.
// Copy the array.
string[] new_values = Values1d.SubArray(1, 3);
The following code shows the extension method that copies part of a two-dimensional array into a new array.
// Copy the indicated entries from a two-dimensional array
// into a new array.
public static T[,] SubArray<T>(this T[,] values,
int row_min, int row_max, int col_min, int col_max)
{
// Allocate the result array.
int num_rows = row_max - row_min + 1;
int num_cols = col_max - col_min + 1;
T[,] result = new T[num_rows, num_cols];
// Get the number of columns in the values array.
int total_cols = values.GetUpperBound(1) + 1;
int from_index = row_min * total_cols + col_min;
int to_index = 0;
for (int row = 0; row <= num_rows - 1; row++)
{
Array.Copy(values, from_index, result, to_index, num_cols);
from_index += total_cols;
to_index += num_cols;
}
return result;
}
This method calculates the number of rows and columns it must copy and creates an array to hold the subarray items.
Next, the code uses values.GetUpperBound to get the number of columns in the original array and uses that value to calculate the index of the first item to copy in the values array. This index is the number of rows that should be skipped times the size of a row, plus the number of columns that should be skipped to reach the first entry.
The code then loops through the necessary number of rows to copy the subarray. For each row that it must copy, the code uses Array.Copy to copy the necessary number of entries from the original array at position from_index into the result array at position to_index. The code then adds the total number of columns in the original array to from_index so it moves to the next row. Similarly it adds the number of columns in the new array to to_index so it moves to the next row in that array.
The following code uses this extension method to copy the items in rows 2-3 and columns 1-3 into a new array.
// Copy the array.
string[,] new_values = Values2d.SubArray(2, 3, 1, 3);
The following code shows the extension method that copies part of a two-dimensional array into an existing array.
// Copy the indicated entries from one two-dimensional
// array into another two-dimensional array.
public static void CopyTo<T>(this T[,] from_array, T[,] to_array,
int from_row_min, int from_row_max, int from_col_min,
int from_col_max, int to_row_min, int to_col_min)
{
// Get the number of columns in each array.
int from_num_cols = from_array.GetUpperBound(1) + 1;
int to_num_cols = to_array.GetUpperBound(1) + 1;
// Get the number of rows and columns we will copy.
int num_rows = from_row_max - from_row_min + 1;
int num_cols = from_col_max - from_col_min + 1;
// Initialize the indices for copying.
int from_index = from_row_min * from_num_cols + from_col_min;
int to_index = to_row_min * to_num_cols + to_col_min;
// Copy.
for (int row = 0; row <= num_rows - 1; row++)
{
Array.Copy(from_array, from_index, to_array, to_index, num_cols);
from_index += from_num_cols;
to_index += to_num_cols;
}
}
This code gets the number of columns in the source and destination arrays and uses those values to calculate the starting indices in both arrays. It then loops through the necessary rows to copy values into the destination array much as the previous extension method copied values into a new array. The only difference is that the values are copied into a specific part of the destination array, not to the destination array's beginning.
The following code uses this extension method to copy the items in rows 2-3 and columns 1-3 into a new array.
// Copy the values and display the result.
private void btnCopy2d2_Click(object sender, EventArgs e)
{
// Allocate a new array.
string[,] new_values = new string[
Values2d.GetUpperBound(0) + 1,
Values2d.GetUpperBound(1) + 1];
// Fill the array with --- values.
for (int row = 0; row <= new_values.GetUpperBound(0); row++)
{
for (int col = 0; col <= new_values.GetUpperBound(1); col++)
{
new_values[row, col] = "------";
}
}
// Copy the values.
Values2d.CopyTo(new_values, 2, 3, 1, 3, 1, 0);
// Display the values.
ShowValues(lstCopy2d2, new_values);
}
This code allocates a new two-dimensional array of the same size as the source array and fills its entries with the value ------. It then uses the CopyTo extension method to copy the subarray in rows 2-3 and columns 1-3 to position [1, 0] in the new array. The method finishes by calling ShowValues to display the result. The ShowValues method is straightforward so I won't show it here.
Download the example to experiment with it and to see additional details.
|