经过使用单行代码完成一样的 10 个练习,咱们来看看 Swift 和其余语言之间的较量。html
使用map来实现java
var arr = [1,2,3,4]; var newArr = arr.map{$0*2} for item in newArr { print(item) }
代码简单明了地完成了数组元素乘2算法
这个问题能够经过使用 reduce
方法和加号运算符解决,这是由于加号运算符实际上也是一个函数。不过这个解法是很是显而易见的,待会儿咱们会看到 reduce
方法更具备创造力的使用。swift
var arr = [1,2,3,4]; let sum = arr.reduce(0, combine: +) print(sum)
咱们使用 contains方法判断一个字符串中是否至少含有一个被选中的关键字:数组
let arr = ["ForrestWoo","Swift1"] let str = "My name is ForrestWoo,I am learning Swift" let query = arr.contains(str.containsString) print(query)
let path = NSBundle.mainBundle().pathForResource("filter", ofType: "rtf")网络
let lines = try? String(contentsOfFile: path!).characters.split{$0 == "\n"}.map(String.init)app
for item in lines! {ide
print(item)函数
}spa
let name = "Forrest" (1...4).forEach{print("Happy Birthday " + (($0 == 3) ? "dear \(name)":"to You"))}
这段代码会将“祝你生日快乐”这首歌的歌词输出到控制台中,它在一段区间内简单的使用了 map
函数,同时也用到了三元运算符。
假设咱们须要使用一个给定的过滤函数将一个序列(sequence)分割为两部分。不少语言除了有常规的map
,flatMap
,reduce
,filter
等函数外,还有一个 partitionBy
函数刚好能够完成这个需求。正如你所知,Swift 没有相似的函数(咱们不想在这里使用 NSArray 中的函数,并经过NSPredicate 实现过滤功能)。
因此,咱们能够经过拓展 SequenceType
,并为它添加 partitionBy
函数来解决这个问题。咱们使用这个函数将整数数组分割为两部分:
extension SequenceType{ typealias Element = Self.Generator.Element func partitionBy(fu: (Element)->Bool)->([Element],[Element]){ var first=[Element]() var second=[Element]() for el in self { if fu(el) { first.append(el) }else{ second.append(el) } } return (first,second) } } let part = [82, 58, 76, 49, 88, 90].partitionBy{$0 < 60} part // ([58, 49], [82, 76, 88, 90])
实际上,这不是单行代码,并且使用了命令式的解法。能不能使用 filter
对它略做改进呢?
extension SequenceType{ func anotherPartitionBy(fu: (Self.Generator.Element)->Bool)->([Self.Generator.Element],[Self.Generator.Element]){ return (self.filter(fu),self.filter({!fu($0)})) } } let part2 = [82, 58, 76, 49, 88, 90].anotherPartitionBy{$0 < 60} part2 // ([58, 49], [82, 76, 88, 90])
这种解法略好一些,可是他遍历了序列两次。并且为了用单行代码实现,咱们删除了闭合函数,这会致使不少重复的内容(过滤函数和数组会在两处被用到)。
能不能只用单个数据流就对原来的序列进行转换,把两个部分分别存入一个元组中呢?答案是是能够的,使用 reduce
方法:
var part3 = [82, 58, 76, 49, 88, 90].reduce( ([],[]), combine: { (a:([Int],[Int]),n:Int) -> ([Int],[Int]) in (n<60) ? (a.0+[n],a.1) : (a.0,a.1+[n]) }) part3 // ([58, 49], [82, 76, 88, 90])
这里咱们建立了一个用于保存结果的元组,它包含两个部分。而后依次取出原来序列中的元素,根据过滤结果将它放到第一个或第二个部分中。
咱们终于用真正的单行代码解决了这个问题。不过有一点须要注意,咱们使用 append
方法来构造两个部分的数组,因此这实际上比前两种实现慢一些。
上述的某些语言不须要依赖外部的库,并且默认有不止一种方案能够处理 XML 格式的数据(好比 Scala 自身就能够将 XML 解析成对象,尽管实现方法比较笨拙),可是 (Swift 的)Foundation 库仅提供了 SAX 解析器,叫作 NSXMLParser。你也许已经猜到了:咱们不打算使用这个。
在这种状况下,咱们能够选择一些开源的库。这些库有的用 C 实现,有的用 Objective-C 实现,还有的是纯 Swift 实现。
此次,咱们打算使用纯 Swift 实现的库:AEXML:
let xmlDoc = try? AEXMLDocument(xmlData: NSData(contentsOfURL: NSURL(string:"https://www.ibiblio.org/xml/examples/shakespeare/hen_v.xml")!)!) if let xmlDoc=xmlDoc { var prologue = xmlDoc.root.children[6]["PROLOGUE"]["SPEECH"] prologue.children[1].stringValue // Now all the youth of England are on fire, prologue.children[2].stringValue // And silken dalliance in the wardrobe lies: prologue.children[3].stringValue // Now thrive the armourers, and honour's thought prologue.children[4].stringValue // Reigns solely in the breast of every man: prologue.children[5].stringValue // They sell the pasture now to buy the horse, }
咱们有多种方式求出 sequence 中的最大和最小值,其中一种方式是使用 minElement
和maxElement
函数:
某些语言支持用简单透明的方式容许对序列的并行处理,好比使用 map
和 flatMap
这样的函数。这使用了底层的线程池,能够加速多个依次执行但又彼此独立的操做。
Swift 还不具有这样的特性,但咱们能够用 GCD 实现:
http://moreindirection.blogspot.it/2015/07/gcd-and-parallel-collections-in-swift.html
古老而优秀的埃拉托色尼选筛法被用于找到全部小于给定的上限 n 的质数。
首先将全部小于 n 的整数都放入一个序列(sequence)中,这个算法会移除每一个数字的倍数,直到剩下的全部数字都是质数。为了加快执行速度,咱们其实没必要检查每个数字的倍数,当检查到 n 的平方根时就能够中止。
基于以上定义,最初的实现多是这样的:
var n = 50 var primes = Set(2...n) (2...Int(sqrt(Double(n)))).forEach{primes.subtractInPlace((2*$0).stride(through:n, by:$0))} primes.sort()
在外层的区间里,咱们遍历每个须要检查的数字。对于每个数字,咱们使用stride(through:Int by:Int)
函数计算出由它的倍数构成的序列。最初,咱们用全部 2 到 n 的整数构造了一个集合(Set),而后从集合中减掉每个生成的序列中的元素。
不过正如你所见,为了真正的删除掉这些倍数,咱们使用了一个外部的可变集合,这会带来反作用。
咱们老是应该尝试消除反作用,因此咱们先计算全部的子序列,而后调用 flatMap
方法将其中全部的元素展开,存放到单个数组中,最后再从原始的集合中删除这些整数。
var sameprimes = Set(2...n) sameprimes.subtractInPlace((2...Int(sqrt(Double(n)))) .flatMap{ (2*$0).stride(through:n, by:$0)}) sameprimes.sort()
既然是福利,天然并不是每一个人都知道这一点。和其余具备元组类型的语言同样,Swift 的元组能够被用来交换两个变量的值,代码很简洁:
var a=1,b=2 (a,b) = (b,a) a //2 b //1
以上就是所有内容,正如咱们预料的那样,Swift 和其余语言同样富有表现力。