文章目录
几年前,函数式编程的复兴正值巅峰,一篇介绍 Scala 中 10 个单行函数式代码的博文在网上走红。很快地,一系列使用其他语言实现这些单行代码的文章也随之出现,比如Haskell, Ruby, Groovy, Clojure, Python,C#, F#, CoffeeScript。
每篇文章都令人印象深刻的揭示了这些语言中一些出色优秀的编程特征。编程高手们利用这些技巧提高编程速度、改进软件质量,编程初学者能从这些简洁的预防中学到各种编程语言的真谛。本《震惊小伙伴的单行代码系列》将逐一介绍这些各种编程语言单行代码文章,供大家学习参考。
震惊小伙伴的单行代码●Erlang 篇
1. 让列表中的每个元素都乘以2
1 | [X * 2 X <- lists:seq (1, 11)]. |
2. 求列表中的所有元素之和
1 | lists:sum (lists:seq (1, 1001)). |
3. 判断一个字符串中是否存在某些词
1 | Wordslist = ["scala", "akka", "play framework", "sbt", "typesafe"].Tweet = "This is an example tweet talking about scala and sbt".[lists:member (S, Wordslist) S <- string:tokens (Tweet, " ")]. |
4. 读取文件
1 | file:read_file ("ten_one_liners.erl"). |
5. 祝你生日快乐!
1 | ["Happy Birthday " ++ case X of 2 -> "dear Robert"; _ -> "You" end X <- lists:seq (1, 4)]. |
6. 过滤列表中的数值
1 | [X X <- lists:seq (40, 60), X >= 50]. |
7. 获取 XML web service 数据并分析
1 | inets:start () .xmerl_scan:string (element (3, element (2, httpc:request ("http://search.twitter.com/search.atom?&q=erlang")))). |
8. 找到列表中最小或最大的一个数字
1 | lists:min (lists:seq (1, 10)) .lists:max (lists:seq (1, 10)). |
9. 并行处理
1 | [spawn (fun () -> io:format ("~w~n", [X * 2]) end) X <- lists:seq (1, 10)]. |
10. “Sieve of Eratosthenes”算法
1 | N = 50.[X X <- lists:usort (lists:seq (2, N + 1)), not lists:member (X, lists:usort ([(P * F) P <- lists:seq (2, round (math:pow (N, 0.5)) + 2), F <- lists:seq (2, round (N / P))]))]. |
震惊小伙伴的单行代码●CoffeeScript 篇
1. 让列表中的每个元素都乘以2
1 | [1..10].map (i) -> i*2 |
或
1 | i * 2 for i in [1..10] |
2. 求列表中的所有元素之和
1 | [1..1000].reduce (t, s) -> t + s |
(reduce == reduceLeft, reduceRight 也可以)
3. 判断一个字符串中是否存在某些词
1 | wordList = ["coffeescript", "eko", "play framework", "and stuff", "falsy"]tweet = "This is an example tweet talking about javascript and stuff."wordList.some (word) -> ~tweet.indexOf word |
下面的例子会返回匹配的单词:
1 | wordList.filter (word) -> ~tweet.indexOf word |
~ is not a special operator in CoffeeScript, just a dirty trick. It is the bitwise NOT operator, which inverts the bits of it’s operand. In practice it equates to -x-1. Here it works on the basis that we want to check for an index greater than -1, and -(-1)-1 == 0 evaluates to false.
4. 读取文件
1 | fs.readFile 'data.txt', (err, data) -> fileText = data |
同步版本:
1 | fileText = fs.readFileSync ('data.txt') .toString () |
In node.js land this is only acceptable for application start-up routines. You should use the async version in your code.
5. 祝你生日快乐!
1 | [1..4].map (i) -> console.log "Happy Birthday " + (if i is 3 then "dear Robert" else "to You") |
下面这一版读起来更像是伪代码:
1 | console.log "Happy Birthday #{if i is 3 then "dear Robert" else "to You"}" for i in [1..4] |
6. 过滤列表中的数值
1 | (if score > 60 then (passed or passed = []) else (failed or failed = [])) .push score for score in [49, 58, 76, 82, 88, 90] |
更函数式的方法:
1 | [passed, failed] = [49, 58, 76, 82, 88, 90].reduce ((p,c,i) -> p[+(c < 60)].push c; p), [[],[]] |
7. 获取 XML web service 数据并分析
这里用 json 代替 XML:
1 | request.get { uri:'path/to/api.json', json: true }, (err, r, body) -> results = body |
8. 找到列表中最小或最大的一个数字
1 | Math.max.apply @, [14, 35, -7, 46, 98] # 98Math.min.apply @, [14, 35, -7, 46, 98] # -7 |
9. 并行处理
Not there yet. You can create child processes on your own and communicate with them, or use the WebWorkers API implementation. Skipping over.
10. “Sieve of Eratosthenes”算法
下面的代码可以写成一行吗?
1 | sieve = (num) -> numbers = [2..num] while ((pos = numbers[0]) * pos) <= num delete numbers[i] for n, i in numbers by pos numbers.shift () numbers.indexOf (num) > -1 |
跟紧凑的版本:
1 | primes = []primes.push i for i in [2..100] when not (j for j in primes when i % j == 0) .length |
真正的一行实现:
1 | (n) -> (p.push i for i in [2..n] when not (j for j in (p or p=[]) when i%j == 0)[0]) and n in p |
1 | (n) -> (p.push i for i in [2..n] when !(p or p=[]) .some ((j) -> |
震惊小伙伴的单行代码●F#篇
1. 让列表中的每个元素都乘以2
1 | [for n in 1..10 -> 2*n] |
2. 求列表中的所有元素之和
1 | Seq.sum [1..1000] |
3. 判断一个字符串中是否存在某些词
1 | Seq.exists tweet.Contains wordList |
4. 读取文件
1 | System.IO.File.ReadAllText "data.txt"System.IO.File.ReadLines "data.txt" |
5. 祝你生日快乐!
1 | for i in 1..4 do printfn "Happy Birthday %s" (if i=3 then "dear NAME" else "to You") |
6. 过滤列表中的数值
1 | let failed, passed = List.partition ((>) 60) [49; 58; 76; 82; 88; 90] |
7. 获取 XML web service 数据并分析
1 | #r "System.Xml.Linq"; System.Xml.Linq.XDocument.Load "data.xml" |
8. 找到列表中最小或最大的一个数字
1 | Seq.min [14; 35; -7; 46; 98]Seq.max [14; 35; -7; 46; 98] |
9. 并行处理
1 | Array.Parallel.map ((*) 2) [1..100] |
10. 素数
1 | Seq.filter (fun i -> Seq.forall (fun j -> i%j<>0) [2..i-1]) [2..50] |
震惊小伙伴的单行代码●R语言篇
1. 让列表中的每个元素都乘以2
1 2 3 4 | #lists lapply (list (1:4),function (n){n*2}) # otherwise (1:4)*2 |
2. 求列表中的所有元素之和
1 2 3 4 5 | #lists lapply (list (1:4),sum) # otherwise sum (unlist (list (1:4))) # or simply sum (1:4) |
3. 判断一个字符串中是否存在某些词
1 | wordlist = c ("lambda", "data", "plot", "statistics", "R") tweet = c ("R is an integrated suite of software facilities for data manipulation, calculation and graphical display") wordlist[wordlist %in% (c(unlist (strsplit (tweet,' ', fixed=T))))] |
4. 读取文件
1 | readLines ("data.file", n=-1) |
5. 祝你生日快乐!
1 | lapply ((1:4),function (x){ paste (c("Happy Birthday to ", ifelse (x!=3, "you", "dear Name")), sep="", collapse="")}) |
6. 过滤列表中的数值
1 | n = c (49, 58, 76, 82, 88, 90); c (list (n[which (n<=60)]),list (n[which (n>60)])) |
7. 获取 XML web service 数据并分析
1 | library ('XML'); xmlParseDoc ('http://search.twitter.com/search.atom?&q=R-Project', asText=F) |
8. 找到列表中最小或最大的一个数字
1 2 3 4 5 6 7 | # for lists lapply (list (c(14, 35, -7, 46, 98)), min, classes="numeric", how="replace") # otherwise min (unlist (list (14, 35, -7, 46, 98))) # or simply min (c(14, 35, -7, 46, 98)) max (c(14, 35, -7, 46, 98)) |
9. 并行处理
1 2 | # http://cran.r-project.org/web/packages/doSMP/vignettes/gettingstartedSMP.pdf # copy from Section 4 An example doSMP sessionlibrary (doSMP); w <- startWorkers (workerCount = 4); registerDoSMP (w); foreach (i = 1:3) %dopar% sqrt (i) |
10. “Sieve of Eratosthenes”算法
1 | ##ok, this one is a little cheatinglibrary ('spuRs'); primesieve (c(),2:50) |
震惊小伙伴的单行代码●Clojure 篇
1、让列表中的每个元素都乘以2
1 | (map #(* % 2) (range 1 11)) |
2、求列表中的所有元素之和
1 | (reduce + (range 1 1001)) |
3、判断一个字符串中是否存在某些词
我这里使用了正则表达式,因为我觉得这是最优方法。
1 2 3 4 | (def tweet "This is an example tweet talking about clojure and emacs.") (def is-word? (set ["clojure" "logic" "compojure" "emacs" "macros"])) (not (nil? (some is-word? (.split tweet " ")))) ; Returns true/false |
4、读取文件
1 2 3 | (def file-text (slurp "data.txt")) ; Reads the whole file (def file-lines (clojure.contrib.io/read-lines "data.txt")) ; Reads as a sequence of lines |
Since Clojure Contrib has been deprecated for future Clojure releases, clojure.contrib.io/read-lines can be rewritten as (line-seq (clojure.java.io/reader (clojure.java.io/file “data.txt”))) in Clojure 1.3 onwards. Thanks to Aaron for pointing it out.
5、祝你生日快乐!
1 | (doseq [l (map #(str "Happy Birthday " (if (= % 2) "dear Rich" "to You")) (range 4))] (println l)) |
或者
1 | (dotimes [n 4] (println "Happy Birthday " (if (= n 2) "dear Rich" "to You"))) |
6. 过滤列表中的数值
1 | (partition-by #(> % 60) [49 58 76 82 88 90]) |
7. 获取 XML web service 数据并分析
1 | (clojure.xml/parse "http://search.twitter.com/search.atom?&q=clojure") |
8. 找到列表中最小或最大的一个数字
1 2 3 4 | (reduce max [14 35 -7 46 98]) (reduce min [14 35 -7 46 98]) ;;Now both together ((juxt #(reduce max %)#(reduce min %)) [14 35 -7 46 98]) ;Returns [98 -7] |
9. 并行处理
;; Assuming process-line to be a CPU intensive function that operates on a line (pmap process-line lines) ; Note the “p” in front of map
10. “Sieve of Eratosthenes”算法
I don’t I have a sufficiently good (in terms of performance & beauty) one line implementation of SoE. I would recommend checking out Christophe Grand’s treatise on the subject titled Everybody loves the Sieve of Eratosthenes for a great discussion on writing real world prime sieves in Clojure.
震惊小伙伴的单行代码●Haskell 篇
1、让列表中的每个元素都乘以2
1 | map (*2) [1..10] |
2、求列表中的所有元素之和
1 2 3 | foldl (+) 0 [1..1000] -- or bettersum [1..1000] |
3、判断一个字符串中是否存在某些词
1 2 3 4 5 6 7 | import Data.List let wordlist = ["monad", "monoid", "Galois", "ghc", "SPJ"] let tweet = "This is an example tweet talking about SPJ interviewing with Galois" or $ map (flip isInfixOf tweet) wordlist-- or better any (flip isInfixOf tweet) wordlist |
4、读取文件
1 2 3 4 | fileText <- readFile "data.txt" let fileLines = lines fileText-- or better let fileLines = fmap lines $ readFile "data.txt" |
5、祝你生日快乐!
1 | mapM_ putStrLn ["Happy Birthday " ++ (if x == 3 then "dear NAME" else "to You") x <- [1..4]] |
6. 过滤列表中的数值
1 | let (passed, failed) = partition (>60) [49, 58, 76, 82, 88, 90] |
7. 获取 XML web service 数据并分析
下面的例子需要使用 curl
和 xml
代码库,参考 RWH 里提供的安装方法。
1 2 3 4 5 6 7 | import Network.Curl import Text.XML.Light import Control.Monad let results = liftM parseXMLDoc $ liftM snd (curlGetString "http://search.twitter.com/search.atom?&q=haskell" []) -- or better Control.Applicative let results = parseXMLDoc . snd <$> curlGetString "http://search.twitter.com/search.atom?&q=haskell" [] |
8. 找到列表中最小或最大的一个数字
1 2 3 4 5 | foldl1 min [14, 35, -7, 46, 98] foldl1 max [14, 35, -7, 46, 98] -- or better minimum [14, 35, -7, 46, 98] maximum [14, 35, -7, 46, 98] |
9. 并行处理
下面的例子需要使用 parallel
代码包。
1 2 3 | import Control.Parallel import Control.Parallel.Strategies parMap rseq (*2) [1..100] |
10. 素数生成器
1 2 | let pgen (p:xs) = p : pgen [xx <- xs, x `mod` p > 0] take 40 (pgen [2..]) |
震惊小伙伴的单行代码●Groovy 篇
1、让列表中的每个元素都乘以2
1 | (1..10)*.multiply (2) |
2、求列表中的所有元素之和
1 | (1..1000) .sum () |
3、判断一个字符串中是否存在某些词
1 2 3 | def wordList = ['groovy', 'akka', 'grails framework', 'spock', 'typesafe'] def tweet = 'This is an example tweet talking about groovy and spock.' wordList.any { word -> tweet.contains (word) } |
4、读取文件
1 2 | def fileText = new File ('data.txt') .text def fileLines = new File ('data.txt') .readLines () |
5、祝你生日快乐!
1 | (1..4) .each { println 'Happy Birthday ' + ((it == 3) ? 'dear Arturo' : 'to You') } |
6. 过滤列表中的数值
1 | def (passed, failed) = [49, 58, 76, 82, 88, 90].split{ it > 60 } |
7. 获取 XML web service 数据并分析
1 | def results = new XmlSlurper () .parse ('http://search.twitter.com/search.atom?&q=groovy') |
8. 找到列表中最小或最大的一个数字
1 2 | [14, 35, -7, 46, 98].min () [14, 35, -7, 46, 98].max () |
9. 并行处理
1 2 | import groovyx.gpars.* GParsPool.withPool { def result = dataList.collectParallel { processItem (it) } } |
Gpars 提供了直观安全的在 Groovy 里执行并行任务。
10. “Sieve of Eratosthenes”算法
1 2 | def t = 2..100 (2..Math.sqrt (t.last ())) .each { n -> t -= ((2*n)..(t.last ())) .step (n) }println t |
震惊小伙伴的单行代码●Swift 篇
1、让列表中的每个元素都乘以2
1 | (1...1024) .map{$0 * 2} |
2、求列表中的所有元素之和
1 | (1...1024) .reduce (0,combine: +) |
3、判断一个字符串中是否存在某些词
1 2 3 | let words = ["Swift","iOS","cocoa","OSX","tvOS"] let tweet = "This is an example tweet larking about Swift" let valid = !words.filter ({tweet.containsString ($0)}) .isEmptyvalid //true |
或
1 | words.contains (tweet.containsString) |
或
1 2 3 4 5 | tweet.characters .split (" ") .lazy .map (String.init) .contains (Set (words) .contains) |
4、读取文件
和其他语言不同,Swift 不能使用内建的函数读取文件,并把每一行存放到数组中。不过我们可以结合 split
和 map
方法写一段简短的代码,这样就无需使用 for
循环:
1 2 3 4 5 6 7 8 | let path = NSBundle.mainBundle () .pathForResource ("test", ofType: "txt") let lines = try? String (contentsOfFile: path!) .characters.split{$0 == "\n"}.map (String.init) if let lines=lines { lines[0] // O! for a Muse of fire, that would ascend lines[1] // The brightest heaven of invention! lines[2] // A kingdom for a stage, princes to act lines[3] // And monarchs to behold the swelling scene. } |
最后一步使用 map
函数和字符串的构造方法,将数组中的每个元素从字符数组(characters)转换为字符串。
5、祝你生日快乐!
1 2 | let name = "uraimo" (1...4) .forEach{print ("Happy Birthday " + (($0 == 3) ? "dear \(name)":"to You"))} |
6、过滤列表中的数值
假设我们需要使用一个给定的过滤函数将一个序列(sequence)分割为两部分。很多语言除了有常规的 map
, flatMap
, reduce
, filter
等函数外,还有一个 partitionBy
函数恰好可以完成这个需求。正如你所知,Swift 没有类似的函数(我们不想在这里使用 NSArray中的函数,并通过 NSPredicate实现过滤功能)。
所以,我们可以通过拓展 SequenceType
,并为它添加 partitionBy
函数来解决这个问题。我们使用这个函数将整数数组分割为两部分:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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
对它略作改进呢?
1 2 3 4 5 6 7 | 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
方法:
1 2 3 4 5 | 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
方法来构造两个部分的数组,所以这实际上比前两种实现慢一些。
7. 获取 XML web service 数据并分析
上述的某些语言不需要依赖外部的库,而且默认有不止一种方案可以处理 XML 格式的数据(比如 Scala 自身就可以将 XML 解析成对象,尽管实现方法比较笨拙),但是 (Swift 的)Foundation 库仅提供了 SAX 解析器,叫做 NSXMLParser。你也许已经猜到了:我们不打算使用这个。
在这种情况下,我们可以选择一些开源的库。这些库有的用 C 实现,有的用 Objective-C 实现,还有的是纯 Swift 实现。
这次,我们打算使用纯 Swift 实现的库: AEXML:
1 2 3 4 5 6 7 8 9 | 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, } |
8. 找到列表中最小或最大的一个数字
1 2 3 4 5 6 7 8 | //Find the minimum of an array of Ints [10,-22,753,55,137,-1,-279,1034,77].sort () .first [10,-22,753,55,137,-1,-279,1034,77].reduce (Int.max, combine: min) [10,-22,753,55,137,-1,-279,1034,77].minElement () //Find the maximum of an array of Ints [10,-22,753,55,137,-1,-279,1034,77].sort () .last [10,-22,753,55,137,-1,-279,1034,77].reduce (Int.min, combine: max) [10,-22,753,55,137,-1,-279,1034,77].maxElement () |
9. 并行处理
某些语言支持用简单透明的方式允许对序列的并行处理,比如使用 map
和flatMap
这样的函数。这使用了底层的线程池,可以加速多个依次执行但又彼此独立的操作。
Swift 还不具备这样的特性,但我们可以用 GCD 实现:http://moreindirection.blogspot….llections-in-swift.html
10. “Sieve of Eratosthenes”算法
古老而优秀的埃拉托色尼选筛法被用于找到所有小于给定的上限 n 的质数。
首先将所有小于 n 的整数都放入一个序列(sequence)中,这个算法会移除每个数字的倍数,直到剩下的所有数字都是质数。为了加快执行速度,我们其实不必检查每一个数字的倍数,当检查到 n 的平方根时就可以停止。
基于以上定义,最初的实现可能是这样的:
1 2 3 | 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
方法将其中所有的元素展开,存放到单个数组中,最后再从原始的集合中删除这些整数。
1 2 3 4 | var sameprimes = Set (2...n) sameprimes.subtractInPlace ((2...Int (sqrt (Double (n)))) .flatMap{ (2*$0) .stride (through:n, by:$0)}) sameprimes.sort () |
这种写法更加清楚,它也是使用 flatMap展开嵌套数组这篇文章很好的一个例子。
震惊小伙伴的单行代码●C#篇
1、让列表中的每个元素都乘以2
1 | Print ("Multiple each item in a list by 2", Enumerable.Range (1, 10) .Select (i => i * 2)); |
2、求列表中的所有元素之和
1 | Print ("Sum a list of numbers", Enumerable.Range (1, 1000) .Sum ()); |
3、判断一个字符串中是否存在某些词
1 2 3 4 | var wordlist = new[] { "C#", "and stuff" }; var tweet = "This is an example tweet talking about C# and stuff"; Print ("Verify if a word exists in string", wordlist.Any (word => tweet.IndexOf (word) > -1)); Print ("Show matched words in string", wordlist.Where (word => tweet.IndexOf (word) > -1)); |
4、读取文件
1 | Print ("Read in a File", File.ReadAllBytes ("oneliners.exe") .Length); |
5、祝你生日快乐!
1 | Print ("Happy Birthday", Enumerable.Range (1, 4) .Select ((i) => string.Format ("Happy Birthday {0} ", i == 3 ? "dear NAME" : "to You"))); |
6. 过滤列表中的数值
1 2 3 4 5 | var passed = new List<int>(); var failed = new List<int>();(from bucket in new[] { passed, failed } from i in new[] { 49, 58, 76, 82, 88, 90 } select new { bucket, i }) .ToList () .ForEach ((tuple) => tuple.bucket.AddRange (Enumerable.Repeat (tuple, 1) .Where ((tup) => (tup.bucket == passed && tup.i > 60) (tup.bucket == failed && tup.i <= 60)) .Select ((tup) => tup.i))); Print ("Filter list of numbers >60", (IEnumerable<int>) passed); Print ("Filter list of numbers <=60", (IEnumerable<int>) failed); |
7. 获取 XML web service 数据并分析
1 | Print ("Fetch and Parse an XML web service", XDocument.Load ("http://search.twitter.com/search.atom?&q=scala")); |
8. 找到列表中最小或最大的一个数字
1 2 | Print ("Find minimum in a list", Enumerable.Min (new[] { 14, 35, -7, 46, 98 })); Print ("Find maximum in a list", Enumerable.Max (new[] { 14, 35, -7, 46, 98 })); |
9. 并行处理
1 | Print ("Parallel Processing", Enumerable.Range (1, 10) .AsParallel () .Select ((i)=>i*2) .AsEnumerable ()); |
10. “Sieve of Eratosthenes”算法
1 | Print ("Sieve of Eratosthenes", Enumerable.Range (1, 9999) .Select (num => { return Enumerable.Range (2, num) .Count (der => num % der == 0) > 1 ? 1 : num; }) .Where (p => p != 1)); |
震惊小伙伴的单行代码●Python 篇
1、让列表中的每个元素都乘以2
1 | print map (lambda x: x * 2, range (1,11)) |
2、求列表中的所有元素之和
1 | print sum (range (1,1001) |
3、判断一个字符串中是否存在某些词
1 2 3 | wordlist = ["scala", "akka", "play framework", "sbt", "typesafe"] tweet = "This is an example tweet talking about scala and sbt." print map (lambda x: x in tweet.split (),wordlist) |
4、读取文件
1 | print open ("ten_one_liners.py") .readlines () |
5、祝你生日快乐!
1 | print map (lambda x: "Happy Birthday to " + ("you" if x != 2 else "dear Name"),range (4)) |
6. 过滤列表中的数值
1 | print reduce (lambda (a,b),c: (a+[c],b) if c > 60 else (a,b + [c]), [49, 58, 76, 82, 88, 90],([],[])) |
7. 获取 XML web service 数据并分析
1 2 3 4 | from xml.dom.minidom import parse, parseStringimport urllib2 # 注意,我将它转换成 XML 格式化并打印出来 print parse (urllib2.urlopen ("http://search.twitter.com/search.atom?&q=python")) .toprettyxml (encoding="utf-8") |
8. 找到列表中最小或最大的一个数字
1 | print min ([14, 35, -7, 46, 98]) print max ([14, 35, -7, 46, 98]) |
9. 并行处理
1 2 3 | import multiprocessing import math print list (multiprocessing.Pool (processes=4) .map (math.exp,range (1,11))) |
10. “Sieve of Eratosthenes”算法
Python 里没有 Sieve of Eratosthenes 操作符,但这对于 Python 来说并不是难事。
1 2 | n = 50 # We want to find prime numbers between 2 and 50 print sorted (set (range (2,n+1)) .difference (set ((p * f) for p in range (2,int (n**0.5) + 2) for f in range (2,(n/p) +1)))) |
震惊小伙伴的单行代码●Ruby 篇
1、让列表中的每个元素都乘以2
1 | (1..10) .map { n n * 2 } |
2、求列表中的所有元素之和
1 | (1..1000) .inject { sum, n sum + n } |
或者使用原生的 Symbol#to_proc 语法,这种语法出现在 Ruby 1.8.7:
1 | (1..1000) .inject (&:+) |
或者直接传人 symbol:
1 | (1..1000) .inject (:+) |
3、判断一个字符串中是否存在某些词
1 2 3 | words = ["scala", "akka", "play framework", "sbt", "typesafe"] tweet = "This is an example tweet talking about scala and sbt." words.any? { word tweet.include?(word) } |
4、读取文件
1 2 | file_text = File.read ("data.txt") file_lines = File.readlines ("data.txt") |
按数组读取时每行结尾字符都是 “\n” 换行符,你可以接着使用代码.map { str str.chop }
去掉它们,或者使用下面的替代方法:
1 | File.read ("data.txt") .split (/\n/) |
5、祝你生日快乐!
1 | 4. times { n puts "Happy Birthday #{n==2 ? "dear Tony" : "to You"}" } |
6. 过滤列表中的数值
1 | [49, 58, 76, 82, 88, 90].partition { n n > 60 } |
7. 获取 XML web service 数据并分析
1 2 3 | require 'open-uri' require 'hpricot' results = Hpricot (open ("http://search.twitter.com/search.atom?&q=scala")) |
这个例子里需要使用 open-uri 和 hpricot 代码库 (你也可以自己写一个)。代码不多,但 Scala 里的方法更优秀。
8. 找到列表中最小或最大的一个数字
1 2 | [14, 35, -7, 46, 98].min [14, 35, -7, 46, 98].max |
9. 并行处理
1 2 3 4 | require 'parallel' Parallel.map (lots_of_data) do chunk heavy_computation (chunk) end |
这跟 Scala 语言不一样,Ruby 里的多核支持不是内置的。它需要使用parallel 或其它类似的 gem。
10. “Sieve of Eratosthenes”算法
Scala 语言里一行代码就能完成,但可读性不好,在 Ruby 里可以简单的实现,但不是一行代码:
1 2 3 4 5 6 7 | index = 0 while primes[index]**2 <= primes.last prime = primes[index] primes = primes.select { x x == prime x % prime != 0 } index += 1 end p primes |
这个例子直接拷贝自 StackOverflow。不是特别简洁,但你可以看明白。
震惊小伙伴的单行代码●Scala 篇
1. 让列表中的每个元素都乘以2
map
函数能将列表中的每个元素依次取出,并用指定的函数依次处理每个元素。在下面的例子里,我们将依次取出每个列表元素,并将它们依次乘以2。这些操作执行完成之后,返回的列表包含的元素个数不变。这是跟reduceLeft
和 foldLeft
等只返回一个值的函数的不同之处。
1 | (1 to 10) map { _ * 2 } |
2. 求列表中的所有元素之和
reduceLeft
函数最常用的功能是求列表里的所有元素之和。下面的例子里,我们使用range
函数创建一个1
到1000
的列表,然后用reduceLeft
遍历每个元素,相加求和。(附增用更简单的内置函数sum
求和。)
1 | (1 to 1000) .reduceLeft ( _ + _ ) |
或
1 | (1 to 1000) .sum |
3. 判断一个字符串中是否存在某些词
下面的例子中,如果字符串中包含列表中的某个单词,则返回真,否则假。我常使用这个技巧来检查一条微博里是否含有我感兴趣的词汇。从技术上将下面是三行代码,但前两行只能算作变量。
1 2 3 | val wordList = List ("scala", "akka", "play framework", "sbt", "typesafe") val tweet = "This is an example tweet talking about scala and sbt." (wordList.foldLeft (false)( _ tweet.contains (_) )) |
或
1 | wordList.exists (tweet.contains) |
4. 读取文件
如果你是使用 Java 编程的程序员,这一行代码也许会让你惊讶,而在 Scala 里用一行代码就能读取和分析文件是很常见的事。下面是读取一个文件的两个例子,一个将整个文件读取都一个字符串里,另外一个读取文件并按行装入一个列表里。
1 2 | val fileText = io.Source.fromFile ("data.txt") .mkString val fileLines = io.Source.fromFile ("data.txt") .getLines.toList |
5. 祝你生日快乐!
一行代码打印出“祝你生日快乐!”歌。下面的例子里展示了 Scala 的三元操作和 map
和 foreach
的混合使用。
1 | (1 to 4) .map { i => "Happy Birthday " + (if (i == 3) "dear NAME" else "to You") }.foreach { println } |
6. 过滤列表中的数值
使用 partition
设定的条件将列表中的数字分为两类。下面的例子将学生按分数分为两个列表。
1 | val (passed, failed) = List (49, 58, 76, 82, 88, 90) partition ( _ > 60 ) |
7. 获取 XML web service 数据并分析
因为 XML 是 Scala 中的一个原生结构,所有,分析 XML 是非常容易的。下面的例子是获取并分析 Twitter feed 的例子。
1 | val results = XML.load ("http://search.twitter.com/search.atom?&q=scala") |
8. 找到列表中最小或最大的一个数字
下面的几个例子都使用了reduceLeft
来遍历一个列表中的数据,并使用指定的函数分析它们。附增了使用更简单的 min/max 方法。
1 2 3 4 | List (14, 35, -7, 46, 98) .reduceLeft ( _ min _ ) List (14, 35, -7, 46, 98) .min List (14, 35, -7, 46, 98) .reduceLeft ( _ max _ ) List (14, 35, -7, 46, 98) .max |
9. 并行处理
Scala 里有一个叫做”parallel collections”的集合类型,它能利用多核处理器来处理批量操作,例如foreach
, map
, filter
, 等… 这里有一个视频可以参考。
下面的例子并不完整,但能很好的说明如何使用 parallel collections 并行处理。假设你有一堆数据在dataList
里,有一个函数processItem
来处理它们,但很耗 CPU。下面的这行代码就能让你使用并行技术处理你的数据。
1 | val result = dataList.par.map ( line => processItem (line) ) |
10. “Sieve of Eratosthenes”算法
好吧,这个并不是很使用,技术上将不是一行,因为它使用了之前定义好的操作符,尽管不好阅读,但很强大。Daniel Sobral 发明了 Sieve of Eratosthenes 算法,可以用来判断一个数字是否是素数。
1 | (n: Int) => (2 to n) > (r => r.foldLeft (r.toSet)((ps, x) => if (ps (x)) ps -- (x * x to n by x) else ps)) |
需要使用预定义的>
操作符,它是一个从 F# 语言里借来的语法。你可以参考 Steve Gilham 的博客里的例子。
转载至:博客园