【问题标题】:Sort 2d array rows in ascending order of their first elements in c#在c#中按第一个元素的升序对二维数组行进行排序
【发布时间】:2016-02-17 22:26:10
【问题描述】:

我需要按照第一个元素的升序对二维数组行进行排序,例如示例

{{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; 
}

你能给点建议吗?

提前致谢!

【问题讨论】:

  • 如果你使用List&lt;&gt;,你可以这样做:stackoverflow.com/a/4875763/1156119
  • 你想就地排序吗?
  • 您只想按每行的第一项排序吗?您想如何对{{1,1,3},{1,1,1},{1,1,2}} 进行排序?

标签: c# arrays sorting


【解决方案1】:

遗憾的是,你错过了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]);

【讨论】:

  • 最简单高效的方法。谢谢!
【解决方案2】:

如果性能不重要,那么您可以将二维数组转换为行数组,通过 linq 中的OrderBy 对它们进行排序,提供 Max 作为标准,然后将结果转换回二维数组:

        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);

【讨论】:

    【解决方案3】:

    您不需要任何额外的方法。只需实现上述二维数组的Sort 方法即可。

    此排序算法与一维数组的排序算法相同,只是您还需要第三个循环来交换行的元素。

    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 所指出的,算法当然会变得非常慢。因此,如果性能在这里不重要,请使用它。

    如果您使用jagged array 而不是二维数组,您可以使事情变得更快。 linq 还支持实现 IEnumerable 的一维数组(因此也是锯齿状数组),您可以使用 OrderBy 进行快速排序。

    【讨论】:

    • 请注意,这是非常低效的(非常慢的排序 + 复制整行...)
    • 算法很好。性能对我来说并不重要。谢谢!
    【解决方案4】:

    二维数组不用于排序,但无论如何,您可以这样做

    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();
    

    此实现不会影响性能。有关它的工作原理和一些其他选项的更多说明,请参阅我对How can I sort a large 2d array C#的回答

    【讨论】:

      【解决方案5】:

      如果您想按第一列排序,然后按第二列,然后按第三列,依此类推,您可以这样做:

      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;
          }
      }
      

      【讨论】:

        【解决方案6】:
        Array.Sort(double, (a,b)=>{return a[0]-b[0];});
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-05-23
          • 2021-12-06
          • 2014-06-09
          • 1970-01-01
          • 1970-01-01
          • 2011-10-25
          • 2022-02-12
          相关资源
          最近更新 更多