如果我们要对一个列表进行排序时,在java中我们通常这么做:
// 我们将User按照排序号进行排序
List<User> userList = this.userService.loadAll();
Collections.sort(userList, new Comparator<User>() {
@Override
public int compare(User lh, User rh) {
if (null == lh && null == rh)
return 0;
if (null == lh)
return -1;
if (null == rh)
return 1;
if (lh.getOrderNo() == rh.getOrderNo())
return 0;
return lh.getOrderNo() > rh.getOrderNo() ? 1 : -1;
}
});
那么在Swift中怎么做呢?
Swift标准库提供了名为sort
的方法,会根据您提供的用于排序的闭包函数将已知类型数组中的值进行排序。一旦排序完成,sort(_:)
方法会返回一个与原数组大小相同,包含同类型元素且元素已正确排序的新数组。原数组不会被sort(_:)
方法修改。
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
func backwards(s1: String, s2: String) -> Bool {
return s1 > s2
}
var reversed = names.sort(backwards)
// reversed为["Ewa", "Daniella", "Chris", "Barry", "Alex"]
当然上面的写法是相当冗长的,好在Swift考虑了这种情形,提供了闭包使得我们可以像java中使用匿名类的方式来完成。
闭包表达式语法如下:
{ (parameters) -> returnType in
statements
}
闭包表达式语法可以使用常量、变量和inout
类型作为参数,但不能提供默认值。也可以在参数列表的最后使用可变参数。元组也可以作为参数和返回值。
由此,我们上面的排序可以重写如下:
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversed = names.sort({ (s1: String, s2: String) -> Bool in
return s1 > s2
})
闭包的函数体部分由关键字in
引入。该关键字表示闭包的参数和返回值类型都已定义,下面将是闭包函数体。
由于这个排序函数非常短,我们可以把它们写在一行中,这样代码将变成:
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversed = names.sort({ (s1: String, s2: String) -> Bool in return s1 > s2})
或许你已经对这个排序代码非常满意了。但是别忘了Swift的类型推断功能可不是吹的,因为排序闭包函数是作为sort(_:)
方法的参数传入的,Swift是否可以为我们推断其参数和返回值的类型呢?也就是说我们是否可以将代码精简成下面所示:
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversed = names.sort({ s1, s2 in return s1 > s2})
我可以非常自信的告诉你这是可以的,甚至我们都把返回尖头(->)和括号都去掉了。体验到Swift的强大了吧。不过我要告诉你的是,这里我们还可以继续进行精简。在Swift中如果闭包是单行表达式,这时候可以通过省略return
关键字来隐式返回结果,这样我们代码又可以精简为:
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversed = names.sort({ s1, s2 in s1 > s2})
嗯嗯,我知道你要说什么啦,是的Swift为内联闭包提供了参数名称缩写功能,我们可以通过$0
, $1
, $2
的方式来顺序使用闭包的参数。也就是说我们的代码还可以继续精简为:
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversed = names.sort({$0 > $1})
这时候,因为全部是函数体,所以一并可以把in
关键字省去。
到了这里你是不是对Swift敬仰的犹如…(此处省略若干字)
但是,我要告诉你这不是终极精简,你是否会认为我已经疯了。还好,不是我疯了,是Swift。在Swift中String
类型重新定义了(重载)大于号(>
)的实现,当然也定义了小于号的实现,该函数接受两个String
类型的参数并返回Bool
类型的值。这正好与sort(_:)
方法的第二个参数需要的函数类型相符合,因此我们代码终极精简如下(如有其它更精简可以告诉我,哈哈):
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversed = names.sort(>)
Ok,本次先到这里。我也是刚刚开始接触Swift,感觉非常强大和智能,入门容易,要熟悉和精通有一定难度,但开发效率比oc高。
大家可以关注我的微信公众号(CD826Workshop)来进行交流。