将MultiDimensional数组排列为降序或升序

时间:2013-01-29 06:27:06

标签: c# wpf arrays multidimensional-array

我正在尝试将此多维数组排列为升序或降序。但是,我需要第1列和第2列之间的关系仍然在一起(意味着我需要例如数组[0,1]和数组[0,2]的数据在一起或以某种方式相关。这是我现在的代码。

int[,] time = new int[5,2]{{0,4},{1,5},{5,10},{3,4},{0,2}};
var sorted = from x in Enumerable.Range(0, time.GetLength(0))
                     from y in Enumerable.Range(0, time.GetLength(1))
                     select new{
                         X = x,
                         Y = y,
                         Value = time[x,y]
                    }into point
                    orderby point.Value descending
                    select point;

这有效,但它将我的所有数据分开。有没有办法在保持第1列和第2列的关系的同时对它们进行排序?

6 个答案:

答案 0 :(得分:5)

我很好奇为什么你需要一个多维数组。很明显,您将数据视为"行的一维集合,"而不是"细胞的二维集合。"

为什么不简单地创建一个List(T),其中T是某种Tuple或自定义结构?

从表面上看,似乎你正试图在指甲上使用螺丝刀;确保你为工作挑选合适的工具;)

答案 1 :(得分:2)

听起来您希望将数据存储在多维数组中,但将数组中的每一行保留为单独的原子单元。另外,每个“点”的比较是X,然后是Y.

int[,] time = new int[5, 2] { { 0, 4 }, { 1, 5 }, { 5, 10 }, { 3, 4 }, { 0, 2 } };

var sorted = from x in Enumerable.Range(0, time.GetLength(0))
                     select new Point()
                     {
                         X = time[x,0],
                         Y = time[x,1]
                     } into point
                     orderby point.X ascending , point.Y ascending 
                     select point;

int[,] sortedTime = new int[5,2];
int index = 0;
foreach (var testPoint in sorted)
{
  Point aPoint = (Point) testPoint;
  sortedTime.SetValue(aPoint.X, index, 0);
  sortedTime.SetValue(aPoint.Y, index, 1);

  index++;
}

答案 2 :(得分:0)

看起来你可能只是在过度思考。例如,如果要将点保持在一起并按第一列排序,只需省略第二个Enumerable.Range并手动分配值:

int[,] time = new int[5,2]{{0,4},{1,5},{5,10},{3,4},{0,2}};
var sorted = from x in Enumerable.Range(0, time.GetLength(0))
                     select new{
                         X = time[x,0],
                         Y = time[x,1]
                    }into point
                    orderby point.X descending
                    select point;

正如@Haxx指出的那样,如果第二个值的顺序也很重要,只需将, point.Y descending添加到orderby子句中。

答案 3 :(得分:0)

我还认为应该将此视为行的集合,因为您希望行始终保持在一起。 .NET具有DataTable类型。例如。

        int[,] time = new int[5, 2] { { 0, 4 }, { 1, 5 }, { 15, 10 }, { 3, 4 }, { 0, 2 } };

        DataTable dt = new DataTable();

        dt.Columns.Add("x", System.Type.GetType("System.Int32"));
        dt.Columns.Add("y", System.Type.GetType("System.Int32"));

        for (int i = 0; i < time.Length / 2; i++)
        {
            DataRow dr = dt.NewRow();
            dr[0] = time[i, 0];
            dr[1] = time[i, 1];
            dt.Rows.Add(dr);
        }

        dt.DefaultView.Sort = "x" + " " + "ASC";
        dt = dt.DefaultView.ToTable();

请注意,我需要输入表格列。否则你会按字母顺序排序。我将您的一个数字更改为15,以证明排序适用于整数(15> 3,但按字母顺序“15”<“3”)。如果您真的希望它作为2D阵列返回,请参阅第一个答案。

答案 4 :(得分:0)

最快的方法是实施一些排序算法,如Quicksort,并将其修改为仅使用Compare(i, j)Swap(i, j)函数。 然后,您可以为多维数组实现这些函数并对其进行排序。 这是一个有效的实施方案:

    public static void Main() {
        int[,] time = new int[5, 2] { { 0, 4 }, { 1, 5 }, { 5, 10 }, { 3, 4 }, { 0, 2 } };
        DoSort(time);
    }

    public static void DoSort(int[,] data) {
        Func<int, int, int> comparer = (i, j) => {
            int s1 = Math.Sign(data[i, 0] - data[j, 0]);
            if (s1 != 0) {
                return s1;
            }
            int s2 = Math.Sign(data[i, 1] - data[j, 1]);
            return s2;
        };

        Action<int, int> swapper = (i, j) => {
            var tmp0 = data[i, 0];
            var tmp1 = data[i, 1];
            data[i, 0] = data[j, 0];
            data[i, 1] = data[j, 1];
            data[j, 0] = tmp0;
            data[j, 1] = tmp1;
        };

        int length = data.GetLength(0);
        Quicksort(comparer, swapper, 0, length - 1);
    }

    public static void Quicksort(Func<int, int, int> comparer, Action<int, int> swapper, int left, int right) {
        int i = left, j = right;
        int pivotIdx = (left + right) / 2;

        while (i <= j) {
            while (comparer(i, pivotIdx) < 0) {
                i++;
            }

            while (comparer(j, pivotIdx) > 0) {
                j--;
            }

            if (i <= j) {
                swapper(i, j);
                i++;
                j--;
            }
        }

        // Recursive calls
        if (left < j) {
            Quicksort(comparer, swapper, left, j);
        }

        if (i < right) {
            Quicksort(comparer, swapper, i, right);
        }
    }
}

此代码对数组进行就地排序,因此您不需要额外的内存,最终得到一个有序的多维数组。

答案 5 :(得分:0)

假设:
1。您希望保持项目配对,例如想要{0,4}作为一对,{1,5}作为另一对。
2。升序的预期结果是:{{0,2},{0,4},{1,5},{3,4},{5,10}}。

正如BTownTKD所建议的那样,强烈建议使用一些类/结构来表示你的对,而不是使用多维数组。您可以使用以下任一列表/数组:

  • Tuple<int, int>
  • KeyValuePair<int, int>
  • 您自己的结构IntPair,具有两个属性X和Y。

这不仅可以帮助您排序,还可以轻松地进行进一步的操作。仅当您有非常特殊的需要时才使用多维数组。

以下是使用Tuple的示例代码:

List<Tuple<int, int>> time = new List<Tuple<int, int>>(){
    new Tuple<int, int>(0,4),
    new Tuple<int, int>(1,5),
    new Tuple<int, int>(5,10),
    new Tuple<int, int>(3,4),
    new Tuple<int, int>(0,2)
};

//Sort Ascending
time.Sort((first, second) =>
    {
        var item1Compare = first.Item1.CompareTo(second.Item1);
        return item1Compare == 0 ? first.Item2.CompareTo(second.Item2) : item1Compare;
    });
//Sort Descending
/*time.Sort((first, second) =>
    {
        var item1Compare = second.Item1.CompareTo(first.Item1);
        return item1Compare == 0 ? second.Item2.CompareTo(first.Item2) : item1Compare;
    });*/