13

Suppose you have an array like:

double[,] rectArray = new double[10,3];

Now you want the fouth row as a double[] array of 3 elements without doing:

double[] fourthRow = new double[]{rectArray[3,0],
                                  rectArray[3,1], 
                                  rectArray[3,2]};

Is it possible someway? Even using a Marshal.Something approach?

Thanks!

Hogan
  • 69,564
  • 10
  • 76
  • 117
abenci
  • 8,422
  • 19
  • 69
  • 134
  • Thinking in C++ while using C# is a pain. How I wonder a solution without copying or jagged array... – Mr. Ree Jul 12 '17 at 09:06

6 Answers6

18

You can use Buffer.BlockCopy method:

const int d1 = 10;
const int d2 = 3;
const int doubleSize = 8;

double[,] rectArray = new double[d1, d2];
double[] target = new double[d2];

int rowToGet = 3;
Buffer.BlockCopy(rectArray, doubleSize * d2 * rowToGet, target, 0, doubleSize * d2);
max
  • 33,369
  • 7
  • 73
  • 84
14

LINQ to the rescue:

var s = rectArray.Cast<double>().Skip(9).Take(3).ToArray();

Explanation: Casting a multi-dimensional array flattens it to a single-dimensional array. After that all we need to do is skip to the element we want (the 4th element in the 2-D array resolves to Skip(9)...) and take 3 elements from it).

code4life
  • 15,655
  • 7
  • 50
  • 82
8

Why not make a generic extension method?

    public static T[] GetRow<T>(this T[,] input2DArray, int row) where T : IComparable
    {
        var width = input2DArray.GetLength(0);
        var height = input2DArray.GetLength(1);

        if (row >= height)
            throw new IndexOutOfRangeException("Row Index Out of Range");
        // Ensures the row requested is within the range of the 2-d array


        var returnRow = new T[width];
        for(var i = 0; i < width; i++)
            returnRow[i] = input2DArray[i, row];

        return returnRow;
    }

Like this all you have to code is:

array2D = new double[,];
// ... fill array here
var row = array2D.GetRow(4) // Implies getting 5th row of the 2-D Array

This is useful if you're trying to chain methods after obtaining a row and could be helpful with LINQ commands as well.

The Don
  • 343
  • 2
  • 13
  • 1
    You got the width and height mixed up – zhujik Apr 26 '17 at 11:41
  • Right you are. Thank you. – The Don Apr 26 '17 at 20:17
  • 1
    The edited and currently presented representation of this solution is not 100% correct. You have to take into account the field of use. If you take the two dimensional array as, e.g., an image, the function is correct. But if you use it as a mathematical matrix – which I guess it should be – the dimensions have to be switched. In a matrix, the first parameter is the count of rows (height alias y) and the second is the count of columns (width alias x). So be aware of the field of use! For mathematical functions, you have to switch the parameter position of 'i' and 'width' in this solution. – Jens Bornschein Jun 07 '17 at 11:25
3

You probably want to use a jagged array. That is not an array of 10 by 3 but instead an array of arrays.

Something like :

        double[][] rectArray;
         ....
        double [] rowArray = rectArray[3];

There are lots of places to learn more about jagged arrays. For example Dynamically created jagged rectangular array

Community
  • 1
  • 1
Hogan
  • 69,564
  • 10
  • 76
  • 117
  • 1
    I need a rectangular array, sorry. – abenci Jun 04 '10 at 19:50
  • 1
    Ok... but you describe a task you want to do that makes more sense with a jagged array. (Which are often faster and smaller anyways.) – Hogan Jun 04 '10 at 19:52
  • @Hogan: I do not understand what you are talking about or referring to. – AMissico Jun 05 '10 at 13:36
  • 1
    @Hogan: Sorry. I think you are confusing me with someone else. I did not answer this question because I am unsure whether Block.BlockCopy is what is needed and I do not fully understand the question. Yet, it is clear the questioner has a requirement to use [,] and suggesting someone replace an implementation is not an answer. Therefore, my down vote and comment to explain why. – AMissico Jun 05 '10 at 15:14
  • 1
    I could delete this answer but I won't even now almost 7 years later it seems useful to leave. There are many answers on SO where the correct answer is "don't do it that way". To assume that an answer is wrong because it looks at the problem from a different direction is a mistake. – Hogan Mar 06 '17 at 15:35
2

If you must use a rectangular array and just want to simplify the syntax, you can use a method to get the row like so:

double[] fourthRow = GetRow(rectArray, 3);

public static T[] GetRow<T>(T[,] matrix, int row)
{
    var columns = matrix.GetLength(1);
    var array = new T[columns];
    for (int i = 0; i < columns; ++i)
        array[i] = matrix[row, i];
    return array;
}
Joseph Sturtevant
  • 13,194
  • 12
  • 76
  • 90
0

Although this is an old thread, an addition to Joseph Sturtevants answer may be useful. His function crashes in case the matrix's first column is not zero, but another integer. This is e.g. always the case in case of retrieving data from Excel, like

object[,] objects = null;
Excel.Range range = worksheet.get_Range("A1", "C5");
objects = range.Cells.Value; //columns start at 1, not at 0

The GetRow function could be modified like this:

    public static T[] GetRow<T>(T[,] matrix, int row, int firstColumn)
    {
        var columns = matrix.GetLength(1);
        var array = new T[columns];
        for (int i = firstColumn; i < firstColumn + columns; ++i)
            array[i-firstColumn] = matrix[row, i];
        return array;
    }
josh
  • 671
  • 5
  • 10