【问题标题】:Arrange MultiDimensional arrays to descending or ascending以降序或升序排列多维数组
【发布时间】:2013-01-29 06:27:06
【问题描述】:

我正在尝试将这个多维数组排列为升序或降序。但是,我需要第 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 列的关系在一起的同时对它们进行排序?

【问题讨论】:

  • 不确定我是否理解您想要实现的目标。你能告诉我们想要的输出吗?

标签: c# wpf arrays multidimensional-array


【解决方案1】:

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

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

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

【讨论】:

  • 感谢您对英语单词的出色使用,遗憾的是它没有帮助,我喜欢使用数组。所以是的。
【解决方案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++;
}

【讨论】:

  • 这很有用,但在我奖励赏金之前,我能否再获得一次帮助?我需要将此处理后的 var 数据存储到另一个多维数组中,但我不知道该怎么做。
  • 我更新了上面的代码示例,将 Point 对象集转换回新的二维数组。这有点做作,可能可以通过更好地了解实际需求进行优化,但对于您的示例应该可以正常工作。
【解决方案3】:

看起来你可能只是想多了。例如,如果您想将这些点保持在一起,并按第一列排序,只需省略第二列 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 子句中即可。

【讨论】:

  • 请注意,它不会以这种方式对 x,y 组合进行排序。这将输出 {{0, 4} {0, 2}, {1, 5}, {3, 4} {5, 10}, };当你升序排序时。 (注意前 2 对)。不确定这是否有问题。
  • 我明白你在说什么。是的,目前还不清楚需要什么。
  • 另外,它会反向输出。 ;)
【解决方案4】:

我还认为应该将其视为行的集合,因为您希望行始终保持在一起。 .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”

【讨论】:

    【解决方案5】:

    最快的方法是实现一些排序算法,如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);
            }
        }
    }
    

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

    【讨论】:

      【解决方案6】:

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

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

      • Tuple&lt;int, int&gt;
      • KeyValuePair&lt;int, int&gt;
      • 您自己的结构 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;
          });*/
      

      【讨论】:

        猜你喜欢
        • 2017-05-16
        • 1970-01-01
        • 2021-06-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多