在 c# 中按 2D 数组行的第一个元素的升序对 2D 数组行进行排序
本文关键字:数组 2D 排序 升序 元素 第一个 中按 | 更新日期: 2023-09-27 18:22:11
我需要按第一个元素的升序对二维数组行进行排序,如示例所示
{{5,7,6},{2,9,6},{4,8,1}} --> {{2,9,6},{4,8,1},{5,7,6}}
我可以在行中找到最大元素,但我现在不知道如何对行进行排序。
public double[] maxInRow(double[,] n)
{
double[] result = new double[n.GetLength(0)];
for (int i = 0; i < n.GetLength(0); i++)
{
double max = 0;
for (int j = 0; j < n.GetLength(1); j++)
{
if (max < n[i,j])
{
max = n[i,j];
}
}
result[i] = max;
}
return result;
}
你能提出一些建议吗?
提前感谢!
可悲的是,有了这个sintax,你错过了linq
的力量,这是.Net framework
最好的组成部分之一,你可以试试这个
double[][] x = new double[2][];
x[0] = new double[] { 5, 2, 5 };
x[1] = new double[] { 6, 8, 3 };
x[2] = new double[] { 8, 3, 6 };
var sortedByFisrtVal = x.OrderBy(y => y[0]);
var sortedBySecondVal = x.OrderBy(y => y[1]);
//trying to guess maybe this is better
var sorted = x.OrderBy(y => y[0]).ThenBy(y => y[1]).ThenBy(y => y[2]);
如果性能不重要,则可以将 2D 数组转换为行数组,通过 linq 中的 OrderBy
对它们进行排序,提供 Max 作为条件,然后将结果转换回 2D 数组:
private static T[][] Convert<T>(T[,] source, int firstDim, int secondDim)
{
T[][] result = new T[firstDim][];
for (int i = 0; i < firstDim; i++)
{
T[] temp = new T[secondDim];
for (int j = 0; j < secondDim; j++)
{
temp[j] = source[i, j];
}
result[i] = temp;
}
return result;
}
private static T[,] ConvertBack<T>(T[][] source, int firstDim, int secondDim)
{
var result = new T[firstDim, secondDim];
for (int i = 0; i < firstDim; i++)
{
for (int j = 0; j < secondDim; j++)
{
result[i, j] = source[i][j];
}
}
return result;
}
// usage sample
double[,] array = { { 5, 7, 6 }, { 2, 9, 6 }, { 4, 8, 1 } };
int firstDim = array.GetUpperBound(0) + 1;
int secondDim = array.GetUpperBound(1) + 1;
double[][] jagged = Convert(array, firstDim, secondDim);
// actual sort is done here!
double[][] sorted = jagged.OrderByDescending(row => row.Max()).ToArray();
double[,] result = ConvertBack(sorted, firstDim, secondDim);
您不需要任何额外的方法。 只需如上所述为 2D 数组实现Sort
方法即可。
此排序算法与 1D 数组的排序算法相同,只是您还需要第三个循环来交换行的元素。
public static void Sort(double[,] n)
{
for (int i = 0; i < n.GetLength(0) - 1; i++)
{
for (int j = i; j < n.GetLength(0); j++)
{
if (n[i, 0] > n[j, 0]) // sort by ascending by first index of each row
{
for (int k = 0; k < n.GetLength(1); k++)
{
var temp = n[i, k];
n[i, k] = n[j, k];
n[j, k] = temp;
}
}
}
}
}
你可以这样称呼它。
Sort(your2dArray);
请注意,算法当然会变得非常慢,正如 Alexei Levenkov 所指出的那样。因此,如果性能在这里不重要,请使用它。
如果您使用交错数组而不是 2D 数组,则可以使事情变得更快。此外,linq 支持实现 IEnumerable 的一维数组(因此也是交错数组(,您可以使用 OrderBy
使用快速排序。
2D 数组不是用于排序的,但无论如何,这是您可以做到这一点的方法
public static class MyAlgorithms
{
public static void SortByFirstColumn<T>(this T[,] array, IComparer<T> comparer = null)
{
// Indirect sorting
var sortIndex = new int[array.GetLength(0)];
for (int i = 0; i < sortIndex.Length; i++)
sortIndex[i] = i;
if (comparer == null) comparer = Comparer<T>.Default;
Array.Sort(sortIndex, (a, b) => comparer.Compare(array[a, 0], array[b, 0]));
// Reorder the array using "in situ" algorithm
var temp = new T[array.GetLength(1)];
for (int i = 0; i < sortIndex.Length; i++)
{
if (sortIndex[i] == i) continue;
for (int c = 0; c < temp.Length; c++)
temp[c] = array[i, c];
int j = i;
while (true)
{
int k = sortIndex[j];
sortIndex[j] = j;
if (k == i) break;
for (int c = 0; c < temp.Length; c++)
array[j, c] = array[k, c];
j = k;
}
for (int c = 0; c < temp.Length; c++)
array[j, c] = temp[c];
}
}
}
并按如下方式使用它
double[,] data = { { 5, 7, 6 }, { 2, 9, 6 }, { 4, 8, 1 } };
data.SortByFirstColumn();
此实现不会影响性能。有关其工作原理和一些其他选项的更多说明,请参阅我的回答 如何对大型 2D 数组 C# 进行排序
如果要按第一列排序,然后按第二列排序,然后按第三列排序,依此类推,则可以这样做:
void Main()
{
var input = new double[,] {{5,7,6},{2,9,6},{2,5,6},{4,8,1}};
Sort(input);
// Input is now:
// {{2,5,6},{2,9,6},{4,8,1},{5,7,6}}
}
public T[,] Sort<T>(T[,] data) where T : IComparable
{
// Transform to array of arrays.
var rows = new T[data.GetLength(0)][];
for (var i = 0; i< data.GetLength(0); ++i)
{
rows[i] = new T[data.GetLength(1)];
for (var j = 0; j < data.GetLength(1); ++j)
rows[i][j] = data[i, j];
}
// Sort rows using a custom array comparer.
Array.Sort(rows, new ArrayComparer<T>());
// Write data back to input array.
for (var i = 0; i< data.GetLength(0); ++i)
for (var j = 0; j < data.GetLength(1); ++j)
data[i, j] = rows[i][j];
return data;
}
public class ArrayComparer<T> : IComparer<T[]> where T : IComparable
{
public int Compare(T[] x, T[] y)
{
var comparer = Comparer<T>.Default;
// Compare elements as long as they're different.
for(var i = 0; i < x.Length; ++i)
{
var compareResult = comparer.Compare(x[i], y[i]);
if (compareResult != 0) return compareResult;
}
return 0;
}
}
Array.Sort(double, (a,b)=>{return a[0]-b[0];});