在原地对 List<Tuple<int, int>> 进行排序

39

如何使用元组的第一个元素作为排序值,对 List<Tuple<int, int>> 进行降序排序? 排序必须是就地进行的,我只知道如何使用 LINQ 进行排序,但那会返回一个新的列表。

7个回答

69

你只需要提供一个 IComparer<Tuple<int, int>> 或者一个 Comparison<Tuple<int, int>>List<T>.Sort方法即可。后者可能更容易内联指定:

list.Sort((x, y) => y.Item1.CompareTo(x.Item1));

如果你想按第一个值排序,然后再按第二个值排序,那就有点棘手了,但仍然可行。例如:

list.Sort((x, y) => {
    int result = y.Item1.CompareTo(x.Item1);
    return result == 0 ? y.Item2.CompareTo(x.Item2) : result;
});

编辑:现在我已经修改了上面的内容,使其按降序排序。请注意,正确的方法是反转比较顺序(从yx而不是从xy)。您不能只取反CompareTo的返回值-当CompareTo返回int.MinValue时,这将失败。


2
根据参考来源,元组具有默认比较器,按照Item1和Item2进行比较。http://referencesource.microsoft.com/#mscorlib/system/tuple.cs,189 - Shital Shah
即使这是旧的,我知道@JonSkeet仍然在四处游荡:(x, y)同时取2个项目吗?因此,当第一个查找开始时,它正在获取list[0]list[1]?另外:ascending order注释已被注释,但未得到回答。它是否与顺序有关,例如(x, y)或(y, x)与随后的代码? - C4d
2
@C4ud3x:(x, y) 是 lambda 表达式的参数列表;lambda 表达式的主体将 xy 进行比较。通过编辑答案使代码按降序排序,回答了该注释。 - Jon Skeet

16
为什么不这样做?
List<Tuple<int, int>> list = ...
list = list.OrderBy(i => i.Item1).ToList();

是的,它创建了一个新的列表,但我只是感兴趣——为什么你不喜欢这样做?


List<Tuple<int, int>> list = new List<Tuple<int, int>>
{
    new Tuple<int,int>(1,1),
    new Tuple<int,int>(0,2),
    new Tuple<int,int>(3,0)
};

list.Sort(Comparer<Tuple<int, int>>.Default);

产生:

0,2
1,1
3,0

它是原地修改的,对吗?


可能是因为它不是原地排序? - R. Martinho Fernandes
1
Tuple<T1, T2> 是否有文档说明按 Item1 然后按 Item2 排序? - Jon Skeet
1
@abatishchev:仅凭一个示例中的备注似乎有些脆弱。我认为我宁愿使用自己的比较器,而不是依赖于仅具有那种保证级别的东西。只是我的个人意见。 - Jon Skeet
@abatishchev:可能没有为很多类型实现-显然是数字和字符串...虽然对于字符串,默认值的行为方式并不是非常明显。 - Jon Skeet
1
你分开回答的后半部分完美地运作了。即使是一个有4个项目的元组,它们也会使用默认比较器正确排序,无论数字数量或其他变化如何。这应该是被选中的答案。干得好! - Hashgrammer
显示剩余3条评论

10
现在你可以使用lambda来完成它:
list = list.OrderByDescending(x => x.Item1).ToList();

4

4
var listSort = from element in list orderby element.Item1  element.Item2 select element;

您,先生,真是个天才!!!我需要按X值对IntPoints列表进行排序。我能够轻松地改编您的示例以满足我的需求。这对我非常有效,我将将其添加到答案中,以防有人需要我的改编版本。非常感谢您的帮助!!! - Toby

0

我需要按照X值对IntPoints列表进行排序。通过修改之前的示例,我成功地完成了这个任务。为了方便以后有需要的人,我将在此处放置我的示例。

//Where edges is an unsorted list of edgepoints returned from the C# A.Forge Library
List<IntPoint> edges

//Sorting on the X value of the Intpoint and returning a new List
List<IntPoint> edgesSorted = (from point in edges orderby point.X select point).ToList();

0
这是一个示例,使用现代元组类型,在 C# 7 中添加。
using System;
using System.Collections.Generic;

namespace SortTuples
{
    class Program
    {
        static void Main(string[] args)
        {
            var data = new List<(string Name, int Grade)>() 
            {
                ("Patrick", 89),
                ("Lucia", 92),
                ("Veronika", 72),
                ("Robert", 78),
                ("Maria", 65),
                ("Andrea", 51),
                ("Ondrej", 45)
            };

            data.Sort((s1, s2) => s1.Name.CompareTo(s2.Name));
            Console.WriteLine(string.Join(", ", data));
  
            data.Sort((s1, s2) => s2.Grade.CompareTo(s1.Grade));
            Console.WriteLine(string.Join(", ", data));
        }
    }
}

输出:

$ dotnet run
(Andrea, 51), (Lucia, 92), (Maria, 65), (Ondrej, 45), (Patrick, 89), (Robert, 78), (Veronika, 72)
(Lucia, 92), (Patrick, 89), (Robert, 78), (Veronika, 72), (Maria, 65), (Andrea, 51), (Ondrej, 45)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接