C#-linq实战003-查询-Where

Source

Where语句检查符合条件的元素,并返回新的迭代器

1:基于谓词筛选值序列

IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)

1.1:foreach解析:

            //IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
            //foreach解析:
            //source:TSource->string
            List<string> fruits15 = new List<string> { "apple", "passionfruit", "banana", "mango",
                    "orange", "blueberry", "grape", "strawberry" };
            //predicate:TSource->item
            Console.WriteLine("基于谓词筛选值序列foreach解析:");
            foreach (string item in fruits15)
            {
                if (item.StartsWith("a"))//predicate:bool->item.StartsWith("a")
                {
                    Console.Write(item + ",");
                }
            }

1.2:原理图:

 1.3:linq写法(查询语句):

            //2:linq写法(查询语句):
            var fruits16 = from f in fruits15.AsEnumerable()
                           where f.StartsWith("a")
                           select f;
            Console.WriteLine("基于谓词筛选值序列linq写法:");
            foreach (string item in fruits16)
            {
                Console.WriteLine(item);

            }

1.4:查询方法写法:

            //3:查询方法写法:
            var fruits17 = fruits15.AsEnumerable().Where(f=> f.StartsWith("a"));
            Console.WriteLine("基于谓词筛选值序列查询方法写法:");
            foreach (string item in fruits17)
            {
                Console.WriteLine(item);

            }

2:基于谓词筛选值序列。 将在谓词函数的逻辑中使用每个元素的索引。

IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)

2.1:foreach解析:

            //IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, int, bool> predicate)
            //foreach解析:
            //source:TSource->string
            List<string> fruits25 = new List<string> { "apple", "passionfruit", "banana", "mango",
                    "orange", "blueberry", "grape", "strawberry" };
            int index = 0;
            //predicate:TSource->item
            //predicate:int->index
            Console.WriteLine("基于谓词筛选值序列foreach解析:");
            foreach (string item in fruits25)
            {
                if (item.StartsWith("a"))//predicate:bool->item.StartsWith("a")
                {
                    Console.Write(item + ",");
                }
                index++;
            }

2.2:原理解析:

​​​​​​​

 

2.2:linq写法(查询语句):没有

2.3:查询方法写法:

            //3:查询方法写法:
            var fruits27 = fruits25.AsEnumerable().Where((f, index25) => f.StartsWith("a") && index25 > 0);
            Console.WriteLine("基于谓词筛选值序列带索引查询方法写法:");
            foreach (string item in fruits27)
            {
                Console.WriteLine(item);

            }

3:多层元素(类)的Where查询:

这里以搜索赛车手为例:

      /// <summary>
    /// 赛车手
    /// </summary>
    [Serializable]
    public class Racer : IComparable<Racer>, IFormattable
    {
        /// <summary>
        /// 名字
        /// </summary>
        public string FirstName { get; set; }
        /// <summary>
        /// 赛车手姓氏
        /// </summary>
        public string LastName { get; set; }
        /// <summary>
        /// 赛车手国家
        /// </summary>
        public string Country { get; set; }
        /// <summary>
        /// 夺冠次数
        /// </summary>
        public int Wins { get; set; }
        public int Starts { get; set; }
        /// <summary>
        /// 赛车手夺冠用的车名称
        /// </summary>
        public IEnumerable<string> Cars { get; private set; }
        /// <summary>
        /// 赛车手夺冠时的年份
        /// </summary>
        public IEnumerable<int> Years { get; private set; }
        public Racer(string firstName, string lastName, string country, int starts, int wins, IEnumerable<int> years, IEnumerable<string> cars)
        {
            this.FirstName = firstName;
            this.LastName = lastName;
            this.Country = country;
            this.Starts = starts;
            this.Wins = wins;
            this.Years = new List<int>(years);
            this.Cars = new List<string>(cars);
        }
        public Racer(string firstName, string lastName, string country, int starts, int wins) : this(firstName, lastName, country, starts, wins, null, null)
        {

        }
        public int CompareTo(Racer other)
        {
            if (other == null) return -1;
            //升序
            //return string.Compare(this.LastName, other.LastName);
            //降序
            return string.Compare(other.LastName, this.LastName);
        }

        public string ToString(string format, IFormatProvider formatProvider)
        {
            switch (format)
            {
                case null:
                case "N":
                    return ToString();
                case "F":
                    return FirstName;
                case "L":
                    return LastName;
                case "C":
                    return Country;
                case "S":
                    return Starts.ToString();
                case "W":
                    return Wins.ToString();
                case "A":
                    return String.Format("{0} {1}, {2}; starts: {3}, wins: {4}",
                          FirstName, LastName, Country, Starts, Wins);
                default:
                    throw new FormatException(String.Format("Format {0} not supported", format));
            }
        }
        public string ToString(string format)
        {
            return ToString(format, null);
        }
        public override string ToString()
        {
            return String.Format("{0} {1}", FirstName, LastName);
        }


    }

 public static class Formula1
    {
        private static List<Racer> racers;
        /// <summary>
        /// 返回一组赛车手,包含了1950-2011年之间的所有一级方程式冠军
        /// </summary>
        /// <returns></returns>
        public static IList<Racer> GetChampions()
        {
            if (racers == null)
            {
                racers = new List<Racer>(40);
                racers.Add(new Racer("Nino", "Farina", "Italy", 33, 5, new int[] { 1950 }, new string[] { "Alfa Romeo" }));
                racers.Add(new Racer("Alberto", "Ascari", "Italy", 32, 10, new int[] { 1952, 1953 }, new string[] { "Ferrari" }));
                racers.Add(new Racer("Juan Manuel", "Fangio", "Argentina", 51, 24, new int[] { 1951, 1954, 1955, 1956, 1957 }, new string[] { "Alfa Romeo", "Maserati", "Mercedes", "Ferrari" }));
                racers.Add(new Racer("Mike", "Hawthorn", "UK", 45, 3, new int[] { 1958 }, new string[] { "Ferrari" }));
                racers.Add(new Racer("Phil", "Hill", "USA", 48, 3, new int[] { 1961 }, new string[] { "Ferrari" }));
                racers.Add(new Racer("John", "Surtees", "UK", 111, 6, new int[] { 1964 }, new string[] { "Ferrari" }));
                racers.Add(new Racer("Jim", "Clark", "UK", 72, 25, new int[] { 1963, 1965 }, new string[] { "Lotus" }));
                racers.Add(new Racer("Jack", "Brabham", "Australia", 125, 14, new int[] { 1959, 1960, 1966 }, new string[] { "Cooper", "Brabham" }));
                racers.Add(new Racer("Denny", "Hulme", "New Zealand", 112, 8, new int[] { 1967 }, new string[] { "Brabham" }));
                racers.Add(new Racer("Graham", "Hill", "UK", 176, 14, new int[] { 1962, 1968 }, new string[] { "BRM", "Lotus" }));
                racers.Add(new Racer("Jochen", "Rindt", "Austria", 60, 6, new int[] { 1970 }, new string[] { "Lotus" }));
                racers.Add(new Racer("Jackie", "Stewart", "UK", 99, 27, new int[] { 1969, 1971, 1973 }, new string[] { "Matra", "Tyrrell" }));
                racers.Add(new Racer("Emerson", "Fittipaldi", "Brazil", 143, 14, new int[] { 1972, 1974 }, new string[] { "Lotus", "McLaren" }));
                racers.Add(new Racer("James", "Hunt", "UK", 91, 10, new int[] { 1976 }, new string[] { "McLaren" }));
                racers.Add(new Racer("Mario", "Andretti", "USA", 128, 12, new int[] { 1978 }, new string[] { "Lotus" }));
                racers.Add(new Racer("Jody", "Scheckter", "South Africa", 112, 10, new int[] { 1979 }, new string[] { "Ferrari" }));
                racers.Add(new Racer("Alan", "Jones", "Australia", 115, 12, new int[] { 1980 }, new string[] { "Williams" }));
                racers.Add(new Racer("Keke", "Rosberg", "Finland", 114, 5, new int[] { 1982 }, new string[] { "Williams" }));
                racers.Add(new Racer("Niki", "Lauda", "Austria", 173, 25, new int[] { 1975, 1977, 1984 }, new string[] { "Ferrari", "McLaren" }));
                racers.Add(new Racer("Nelson", "Piquet", "Brazil", 204, 23, new int[] { 1981, 1983, 1987 }, new string[] { "Brabham", "Williams" }));
                racers.Add(new Racer("Ayrton", "Senna", "Brazil", 161, 41, new int[] { 1988, 1990, 1991 }, new string[] { "McLaren" }));
                racers.Add(new Racer("Nigel", "Mansell", "UK", 187, 31, new int[] { 1992 }, new string[] { "Williams" }));
                racers.Add(new Racer("Alain", "Prost", "France", 197, 51, new int[] { 1985, 1986, 1989, 1993 }, new string[] { "McLaren", "Williams" }));
                racers.Add(new Racer("Damon", "Hill", "UK", 114, 22, new int[] { 1996 }, new string[] { "Williams" }));
                racers.Add(new Racer("Jacques", "Villeneuve", "Canada", 165, 11, new int[] { 1997 }, new string[] { "Williams" }));
                racers.Add(new Racer("Mika", "Hakkinen", "Finland", 160, 20, new int[] { 1998, 1999 }, new string[] { "McLaren" }));
                racers.Add(new Racer("Michael", "Schumacher", "Germany", 287, 91, new int[] { 1994, 1995, 2000, 2001, 2002, 2003, 2004 }, new string[] { "Benetton", "Ferrari" }));
                racers.Add(new Racer("Fernando", "Alonso", "Spain", 177, 27, new int[] { 2005, 2006 }, new string[] { "Renault" }));
                racers.Add(new Racer("Kimi", "Räikkönen", "Finland", 148, 17, new int[] { 2007 }, new string[] { "Ferrari" }));
                racers.Add(new Racer("Lewis", "Hamilton", "UK", 90, 17, new int[] { 2008 }, new string[] { "McLaren" }));
                racers.Add(new Racer("Jenson", "Button", "UK", 208, 12, new int[] { 2009 }, new string[] { "Brawn GP" }));
                racers.Add(new Racer("Sebastian", "Vettel", "Germany", 81, 21, new int[] { 2010, 2011 }, new string[] { "Red Bull Racing" }));
            }

            return racers;
        }
}

示例:这里以1.1的方法变体查询

找出至少赢得15场比赛的巴西和奥地利赛车手

3.1:foreach解析:

            //IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
            //foreach解析:
            //source:TSource->string
            var gc1 = Formula1.GetChampions();
            //predicate:TSource->item
            foreach (var r in gc1)
            {
                //bool的判断使用lambda表达式
                //predicate:bool->r.Wins >= 15 && (r.Country == "Brazil" || r.Country == "Austria")
                if (r.Wins >= 15 && (r.Country == "Brazil" || r.Country == "Austria"))
                {
                    Console.WriteLine("2.1.1:{0:A}", r);
                }
            }

3.2:linq写法(查询语句):

            //2.1:找出至少赢得15场比赛的巴西和奥地利赛车手
            //2.1.1:语法糖
            var racers = from r in Formula1.GetChampions()
                         where r.Wins >= 15 && (r.Country == "Brazil" || r.Country == "Austria")
                         select r;
            foreach (Racer r in racers)
            {
                Console.WriteLine("2.1.1:{0:A}", r);
            }

 3.3:查询方法写法:

            //写法2:2.1.3
            var racers3 = Formula1.GetChampions().Where(r => r.Wins >= 15 && (r.Country == "Brazil" || r.Country == "Austria")).Select(r => r);
            //与写法2一样,select方法可以舍弃
            var racers35 = Formula1.GetChampions().Where(r => r.Wins >= 15 && (r.Country == "Brazil" || r.Country == "Austria"));
            foreach (Racer r in racers3)
            {
                Console.WriteLine("2.1.3:{0:A}", r);
            }