一,什么是LINQ
LINQ 是 Language Integrated Query(语言集成查询)的简称。它是微软在.NET 3.5中引入的重要功能。既然是微软推出的,那对应的编程言自然是c#和Visual Basic语言。
1,LINQ的作用
让我们可以使用相同API(类似SQL的语法来查询)操作不同的数据源。比如:SQL Server、Oracle、XML以及内存中的数据集合,当然开发人员也可以使用其提供的扩展框架添加更多的数据源。
2,LINQ的查询操作符
LINQ定义了大约40个查询操作符,如select、from、in、where以及order by(C#中)等。使用这些操作符可以编写查询语句。
3,LINQ的操作语法
LINQ查询时有两种语法可供选择:查询方法语法(Fluent Syntax)和查询表达式(Query Expression)。
查询方法方式:主要利用System.Linq.Enumerable类中定义的扩展方法和Lambda表达式方式进行查询。
查询语句方式:一种更接近SQL语法的查询方式,可读性更好。
4,LINQ的使用样例
下面以使用LINQ操作内存中的数据集合为例。
比如我们有一个联系人的集合,里面联系人有姓名、年龄、电话这三个属性。我们只想要查出年龄在40岁以下的人员,同时返回的结果集里只需要联系人姓名和年龄即可(注意,这里我们不需要电话)。
那么组合使用where语句和select语句即可,对应的C#代码如下(以查询方法语法为例):
var user1 = new User(){ name = "张三", age = 34, phone = "123456" };
var user2 = new User(){ name = "李四", age = 10, phone = "101" };
var user3 = new User(){ name = "王五", age = 45, phone = "110" };
List<User> userCollection = new List<User>() { user1, user2, user3 };
var results = userCollection
.Where(c => c.age < 40)
.Select(c => new { c.name, c.age });
foreach (var result in results)
{
Console.WriteLine(result.ToString());
}
Console.ReadLine();
二,Swift对LINQ的支持情况
虽然LINQ简单、高效、强大,但由于是.Net上的东西,所以在Swift中无法使用LINQ查询。好在我们可以通过 map、filter、reduce 配合闭包循环来实现类似的功能。
1,还是以上面的联系人样例为例,在Swift中要实现同样的功能可以这么写:
let userCollection = [
(name: "张三", age: 34, phone: "123456"),
(name: "李四", age: 10, phone: "101"),
(name: "王五", age: 45, phone: "110")]
let results = userCollection.lazy
.filter { c in c.age < 45 }
.map { ($0.name, $0.age) }
for result in results {
print(result)
}
2,更多的样例
可以查看GitHub上的一个项目:101 LINQ Samples in Swift 2.0
它提供了一百多个样例,演示了各种LINQ查询在Swift中的替换方法,大家可以去看下。
三,给Swift添加LINQ扩展
有时单纯地使用map、filter、reduce已经不能满足我们的需求,好在网上有大神提供了相关的三方库,让我们在Swift中也能很方便的使用LINQ。下面介绍个人觉得比较优秀扩展库:SINQ。
1,SINQ介绍
顾名思义,SINQ 就是 Swift Integrated Query 的缩写,当然我们也可以称它为 LINQ for Swift。
SINQ使用方式类似于LINQ的查询方法语法(Fluent Syntax),它提供了大量的查询方法,比如:aggregate/reduce, all, any, concat, contains, count, distinct, each, elementAt, except, first, groupBy, groupJoin, intersect, join, last, min/max, argmin/argmax, orderBy, reverse, select map, selectMany, single, skip, take, thenBy/thenByDescending, toArray, toDictionary/toLookupDictionary, union, whereTrue/filter, zip
2,SINQ的安装配置
GitHub地址:https://github.com/slazyk/SINQ
下载后把其中的 SINQ.swift 添加到工程里面即可。
3,SINQ的使用样例
(1)whereTrue 与 select 方法
还是实现上面的同样的功能,查出年龄在40岁以下的人员,同时返回的结果集里只需要联系人姓名和年龄。
let userCollection = [
(name: "张三", age: 34, phone: "123456"),
(name: "李四", age: 10, phone: "101"),
(name: "王五", age: 45, phone: "110")]
let results = sinq(userCollection)
.whereTrue{ $0.age < 40 }
.select{ ($0.name, $0.age) }
for result in results {
print(result)
}
(2)orderBy / orderByDescending 排序方法
查出年龄在40岁以下的人员,同时按照年龄进行升序排列。
let results = sinq(userCollection)
.whereTrue{ $0.age < 40 }
.orderBy{ $0.age }
(3)min / max 取最小最大值方法
查询所有联系人中的最小年龄。
let result = sinq(userCollection).min{ $0.age }
print(result) // 10
(4)argmin / argmax 取得包含最小最大值的元素对象
查询出最小年龄的联系人。
let result = sinq(userCollection).argmin{ $0.age }
print(result) // ("李四", 10, "101")
(5)skip 跳过固定数量的元素,take获取固定数量的元素
查询出第2个和第3个联系人。
let results = sinq(userCollection).skip(1).take(2)
for result in results {
print(result)
}
//("李四", 10, "101")
//("王五", 45, "110")
(6)all 判断所有元素是否都满足条件
判断所有联系人年龄是否都是小于40岁。
let result = sinq(userCollection).all{ $0.age < 40 }
print(result) //false
(7)any 判断是否存在满足条件元素
判断联系人中是否有年龄小于40岁的。
let result = sinq(userCollection).any{ $0.age < 40 }
print(result) //true