If I have a List<List<T>
like the following :
Name City Id
Anna NY 1
Joe NJ 2
How can I transpose it efficiently in order to have :
Name Anna Joe
City NY NJ
Id 1 2
I tried the following
public static void MatrixTranspose<T>(ref List<List<T>> matrix)
{
var h = matrix.Count - 2;
var w = matrix[0].Count - 1;
for (var i = 0; i < h; ++i)
{
for (var j = i + 1; j < w; ++j)
{
var tmp = matrix[i][j];
matrix[i][j] = matrix[j][i];
matrix[j][i] = tmp;
}
}
}
That seems to be working on paper I believe? But I feel like I'm doing too much permutations. Is there a way to optimize it? Also, is the use of ref correct here?
1 Answer 1
is the use of ref correct here?
Taken from MSDN: ref (C# Reference)
The ref keyword causes an argument to be passed by reference, not by value. The effect of passing by reference is that any change to the parameter in the called method is reflected in the calling method. For example, if the caller passes a local variable expression or an array element access expression, and the called method replaces the object to which the ref parameter refers, then the caller’s local variable or the array element now refer to the new object.
The point of ref
is to pass a value type (struct) to a method as if it was reference type (class). List<T>
is a class, so there's no need to add ref
in this scenario as it's just acting as another level of redirection. Think of it as being a pointer to a pointer.
The problem with using List<List<T>
is that the size of the nested lists could differ from the top-level list and this wouldn't be a matrix. I'd recommend that you use something with a guaranteed rectangular structure, such as T[,]
. i.e:
public static void MatrixTranspose<T>(ref T[,] matrix)
{
int columns = matrix.GetLength(0);
int rows = matrix.GetLength(1);
T[,] transposed = new T[rows, columns];
for (int row = 0; row < rows; row++)
{
for (int column = 0; column < columns; column++)
{
transposed[row, column] = matrix[column, row];
}
}
// Reassign matrix so that it gets picked up by ref.
matrix = transposed;
}
string[,]
or evenstring[][]
. Or you may let it beList<List<string>>
but avoid to transpose the matrix. If it's only for visualization/serialization purposes then you just need to read values in the other order. Even better...create aView
of underlying type and keep consumers unaware of its implementation/storage. Just few ideas to consider. \$\endgroup\$