List <t>。使用带有2个参数的Lambda表达式进行排序

时间:2017-09-15 00:02:14

标签: c# sorting lambda

我正在深入阅读C#以尝试更好地理解语言。我之前使用简单的lambda表达式使用单个参数并熟悉它们。我努力的部分是films.Sort((f1, f2) => f1.Name.CompareTo(f2.Name));来对列表进行排序。从我能够弄清楚当我尝试向其添加IComparer<Film>时,lambda表达式的计算结果为f3。被称为IComparer.Compare Method (T, T)的方法确定了项目顺序。

第二个参数让我想说它比较列表中的第N和第N + 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 }
        };
    }
}

2 个答案:

答案 0 :(得分:2)

您无法从方法签名中判断参数的使用次数。我可以编写一个永远不会调用其参数的方法Foo(Func<string, string>)

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

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

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

答案 1 :(得分:0)

实际上,您可以使用LINQ对任何实现IEnumerable<T>接口的类型的元素进行排序,例如List<T>类型:

// 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表达式中一次只选择一个属性。