3

我正在尝试将这个多维数组排列为升序或降序。但是,我需要第 1 列和第 2 列之间的关系仍然在一起(这意味着我需要例如 array[0,1] 和 array[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 列的关系?

4

6 回答 6

5

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

为什么不简单地制作一个List(T),其中 T 是某种元组或自定义结构?

从表面上看,您似乎是在尝试在钉子上使用螺丝刀;确保您为工作选择了正确的工具;)

于 2013-02-08T13:38:45.190 回答
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++;
}
于 2013-02-05T21:41:45.653 回答
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

于 2013-02-05T19:15:27.647 回答
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 数组返回,请参阅第一个答案。

于 2013-02-09T08:11:12.813 回答
0

最快的方法是实现一些排序算法,例如Quicksort并将其修改为仅使用Compare(i, j)andSwap(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);
        }
    }
}

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

于 2013-02-10T20:33:40.647 回答
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。

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

这是使用元组的示例代码:

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;
    });*/
于 2013-02-11T21:46:58.740 回答