【问题标题】:List<T>.Sort using Lambda expression with 2 parametersList<T>.Sort 使用带有 2 个参数的 Lambda 表达式
【发布时间】:2017-09-15 09:56:20
【问题描述】:

我正在阅读 C# In Depths 以尝试更好地理解该语言。我之前使用过带有单个参数的简单 lambda 表达式并且已经熟悉它们。我正在努力解决的部分是films.Sort((f1, f2) =&gt; f1.Name.CompareTo(f2.Name)); 对列表进行排序。据我所知,当我尝试向其添加 f3 时,lambda 表达式的计算结果为 IComparer&lt;Film&gt;。被调用的方法IComparer.Compare Method (T, T) 决定了项目的顺序。

第二个参数让我想说它比较列表中的第 N 和 Nth+1 film,并从 0 到 films.Count-1 进行比较。这个对吗?如果不是,我错在哪一部分。我不想避免错误假设并避免意外错误。

using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {
        var films = GetFilms();

        Action<Film> print = film => Console.WriteLine("Name={0}, Year={1}", film.Name, film.Year);

        Console.WriteLine("All films");
        films.ForEach(print);

        Console.WriteLine();
        Console.WriteLine("Old films");
        films.FindAll(film => film.Year < 1960).ForEach(print);

        Console.WriteLine();
        Console.WriteLine("Sorted films");
        films.Sort((f1, f2) => f1.Name.CompareTo(f2.Name));
        films.ForEach(print);
    }

    class Film
    {
        public string Name { get; set; }
        public int Year { get; set; }
    }

    static List<Film> GetFilms()
    {
        return new List<Film>
        {
            new Film { Name = "Jaws", Year = 1975 },
            new Film { Name = "Singing in the Rain", Year = 1952 },
            new Film { Name = "Some like it Hot", Year = 1959 },
            new Film { Name = "The Wizard of Oz", Year = 1939 },
            new Film { Name = "It's a Wonderful Life", Year = 1946 },
            new Film { Name = "American Beauty", Year = 1999 },
            new Film { Name = "High Fidelity", Year = 2000 },
            new Film { Name = "The Usual Suspects", Year = 1995 }
        };
    }
}

【问题讨论】:

    标签: c# sorting lambda


    【解决方案1】:

    您无法从方法签名中得知该参数将被使用多少次。我可以写一个方法Foo(Func&lt;string, string&gt;) 从来不调用它的参数。

    但是,由于这是一种排序方法,因此对列表进行一次迭代是不够的。有许多不同的排序算法,但它们倾向于使用O(n log(n)) 比较。换句话说,将排序列表的长度加倍将导致对 lambda 函数的调用增加一倍多。

    如果您想查看它运行时实际发生的情况,请添加一些日志记录!

    films.Sort((f1, f2) => 
    {
        Console.WriteLine("Comparing ${f1.Name} to ${f2.Name}");
        return f1.Name.CompareTo(f2.Name);
    });
    

    【讨论】:

    • 遵循您的建议并发现,在这种情况下,它使用了选择排序。看到我可以在 =&gt; 运算符之后使用 { ... } 是有道理的。非常感谢。
    • @IvenBach 很高兴它成功了!使用大括号时存在细微差别;你必须return最终值。
    【解决方案2】:

    实际上,您可以使用 LINQ 对任何实现 IEnumerable&lt;T&gt; 接口的类型(如 List&lt;T&gt; 类型)上的元素进行排序:

    // This will order the films by their name.
    var result1 =
        films
            .OrderBy(film => film.Name)
            .ToList();
    
    // This will order the films first by Year in descending order and 
    // then by Name in ascending order.
    var result2 =
        films
            .OrderByDescending(film => film.Year)
            .ThenBy(film => film.Name)
            .ToList();
    

    您还可以使用ThenByDescending() 方法,如果需要,您还可以从这些方法中创建更长的链。

    问题是在这里你应该在 lambda 表达式中一次只选择一个属性。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-11-06
      • 2010-11-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-22
      相关资源
      最近更新 更多