排序时使用另一个列表执行的交换来排列一个 c# 列表

本文关键字:列表 排列 一个 交换 另一个 执行 排序 | 更新日期: 2023-09-27 18:36:09

我有两个 c# 列表,当我根据某个露营者对一个列表进行排序时,我需要在第一个列表执行交换后对另一个列表进行排序,而不会使用太多额外的空间。

//function 
private int ColumnSortCriteria(List<double> p1, List<double> p2) 
{
    if (p1[0] > p2[0])
        return 1;
    if ((float) p1[0] == (float) p2[0] && p2[1] > p2[1])
        return 1;
    if (p1[0] == p2[0] && p1[1] == p2[1])
        return 0;
    return -1;
}
// main goes from here ......
List<List<double>> WallEndPoints1 = new List<List<double>>();
List<List<double>> WallEndPoints2 = new List<List<double>>();
WallEndPoints1.sort(ColumnSortCriteria)

排序时使用另一个列表执行的交换来排列一个 c# 列表

有点评论(但很长)。

从您的排序标准方法中,我推断您的p1p2(因此您的"内部"List<>)总是有 2 Count。那为什么不对他们使用Tuple<double, double>呢?然后你有:

List<Tuple<double, double>> WallEndPoints1 = new List<Tuple<double, double>>();
List<Tuple<double, double>> WallEndPoints2 = new List<Tuple<double, double>>();

您可以像这样向列表添加点:

WallEndPoints1.Add(Tuple.Create(7.3, -0.5));
// etc.

您的ColumnSortCriteria变得简单:

//function 
static int ColumnSortCriteria(Tuple<double, double> p1, Tuple<double, double> p2) 
{
  // lexicographic
  return System.Collections.StructuralComparisons.StructuralComparer.Compare(p1, p2);
}

然后,如果本着德米特里回答的精神,将两个列表组合(压缩)在一起,你会得到:

List<Tuple<Tuple<double, double>, Tuple<double, double>>> combinedEndPoints
  = WallEndPoints1.Zip(WallEndPoints2, Tuple.Create).ToList();

var关键字的情况?

在这种情况下,您可以像这样排序:

combinedEndPoints.Sort((a, b) => ColumnSortCriteria(a.Item1, b.Item1));

它按第一对(.Item1)对对进行排序,其中第一对按字典顺序进行比较。如果第一对与成对相同,则顺序未定义。

对我来说,这是对你的问题最可能的解释。

也许你想要的是"简单":

combinedEndPoints.Sort(System.Collections.StructuralComparisons.StructuralComparer.Compare);

它按一种"嵌套"或"深度"词典排序对列表进行排序。


当然,如果您不想遵循我的建议并更改WallEndPoints1WallEndPoints2的类型以包括Tuple<,>,解决方案看起来仍然相同:

List<Tuple<List<double>, List<double>>> combinedEndPoints
  = WallEndPoints1.Zip(WallEndPoints2, Tuple.Create).ToList();
combinedEndPoints.Sort((a, b) => ColumnSortCriteria(a.Item1, b.Item1));

现在ColumnSortCriteria是问题中的原始方法(原始签名)。

无论哪种情况,正如 Dmitry 在他的回答中所说,从"组合"列表中选择一个组件以仅查看"1"或仅查看"2",即:

var wallEndPoints1Sorted = combinedEndPoints.Select(x => x.Item1);
var wallEndPoints2Sorted = combinedEndPoints.Select(x => x.Item2);

我建议将两个列表合并为一个:

// I've used Tuple<T1, T2>, but probably you have a better class for point
List<Tuple<Double, Double>> WallEndPoints = new List<Tuple<Double, Double>>() {
  new Tuple<Double, Double>(3.0, 5.0),
  ...
  new Tuple<Double, Double>(15.0, 20.0),
};

然后按第一个组件排序:

WallEndPoints.Sort((left, right) => left.Item1.CompareTo(right.Item1));

或词典(按第一分,按第二分列):

WallEndPoints.Sort((left, right) => {
  int result = left.Item1.CompareTo(right.Item1);
  return result != 0 ? result : left.Item2.CompareTo(right.Item2);  
});

每当你想要第一个/第二个组件时,你可以使用 Linq

var xs = WallEndPoints.Select(item => item.Item1);
var ys = WallEndPoints.Select(item => item.Item2);