排序一个列表<>基于另一个

时间:2013-01-09 03:16:17

标签: c# list generics sorting

说我有

List<int> ages  = new List<int>() { 8, 5, 3, 9, 2, 1, 7 };
List<int> marks = new List<int>() { 12, 17, 08, 15, 19, 02, 11 };

我可以按marksages进行排序:

while (true)
{
  bool swapped = false;

  for (int i = 0; i < ages.Count - 1; i++)
    if (ages[i] > ages[i + 1])
    {
      int tmp = ages[i];
      ages[i] = ages[i + 1];
      ages[i + 1] = tmp;

      tmp = marks[i];
      marks[i] = marks[i + 1];
      marks[i + 1] = tmp;

      swapped = true;
    }

  if (!swapped)
    break;
}

现在我想把它放到一个接受任何两个列表的函数中。第一个参数将是参考列表,数字或可比较列表。第二个参数是包含数据的列表。

例如:

public static void Sort<T>(List<T> RefList, List<T> DataList)
{
  // sorting logic here...
}

有一些问题:

首先,T几乎肯定不是RefListDataList中的同一类型。 RefList可能是日期,整数或双打;而DataList可以完全免费。我需要能够接收两个任意泛型类型。

其次,我似乎无法将>运算符与此行中的T一起使用:

if (ages[i] > ages[i + 1])

也许我的整个方法都是错误的。

顺便说一句,我已阅读过类似问题的回复,这些问题表明这两个列表应合并为一个复合数据类型的列表。这对我的应用来说根本不实用。我想要做的就是编写一个静态函数,以某种方式根据另一个列表的元素对一个列表进行排序。

4 个答案:

答案 0 :(得分:8)

要按照您希望的方式对一个列表进行排序,您需要以某种方式将第一个列表中的项目的引用保留到第二个列表中的权重/键。没有现有方法可以做到这一点,因为您无法轻松地将元数据与任意值相关联(即,如果第一个列表是int的列表,则在您的情况下没有任何内容可以映射到第二个列表中的键)。您唯一合理的选择是同时对2个列表进行排序,并通过索引进行关联 - 再次没有现有的类可以提供帮助。

使用您拒绝的解决方案可能要容易得多。即简单地说Zip和OrderBy,而不是重新创建第一个列表:

ages = ages
  .Zip(marks, (a,m)=> new {age = a; mark = m;})
  .OrderBy(v => v.mark)
  .Select(v=>v.age)
  .ToList();

注意(由phoog提供):如果你需要使用Array进行这种类型的排序,那么Array.Sort就可以完全实现这一操作(详情请参阅phoog的答案)。

答案 1 :(得分:8)

没有框架方法可以使用List<T>执行此操作,但如果您不介意将数据放入两个数组,则可以使用其中一个Array.Sort()重载,它将两个数组作为参数。第一个数组是键,第二个是值,因此您的代码可能如下所示(不考虑从列表中获取数组的步骤):

Array.Sort(ages, marks);

将值放入数组然后返回列表的具体细节取决于您是否需要以适当排序的相同列表结束或者是否可以返回新列表,其中包含所需顺序的数据。

答案 2 :(得分:4)

使用:

public static void Sort<TR, TD>(IList<TR> refList, IList<TD> dataList)
        where TR : System.IComparable<TR>
        where TD : System.IComparable<TD>
{
 ...
}

然后使用:

refList[i].CompareTo(refList[i+1])

而不是运营商。

.Net编号已经实现了IComparable,你可以使用允许你指定不同IComparable的重载。

答案 3 :(得分:2)

如果我理解“我可以按照这样的年龄来分类我的分数:”正确,

我想建议以下消除很多混淆。

struct Student{
    int age;
    int marks;
};

List<Student> students = {{8,12}, ...};

现在您可以根据年龄进行排序,标记会自动排序。

如果不可能,您需要修改以下代码。

  

首先,T几乎肯定与RefList和DataList中的类型不同。

然后你需要2个参数T1,T2。 Just T暗示类型是相同的。

public static void Sort<RefType, DataType>(List<RefType> RefList, List<DataType> DataList)
{

您也可以按照Mechanical Snail的建议压缩两个列表,并在Looping through 2 Lists at once中解释