List comprehension和递归的巧妙结合

我以前总以为list comprehension这个语法糖不过就是些map,filter转换罢了,最近看到Haskell和Erlang的递归用法来实现排列,比循环方法要简洁很多:

Haskell:
java 代码
  1. permutation [] = [[]]     
  2. permutation xs = [x:ys | x <- xs, ys <- permutation (delete x xs)]  

Erlang:
java 代码
  1. permutation([]) -> [[]];  
  2. permutation(L)  -> [[H|T] || H <- L, T <- permutation(L--[H])].  

应用举例

AlbertLee出的一道面试题: http://www.douban.com/group/topic/1237059/
用1、2、2、3、4、5这六个数字(注意有两个2), 打印出所有不同的排列,如:512234、412325等,要求:"4"不能在第三位,"3"与"5"不能相连。

我稍微改了一下的Haskell解法如下:
java 代码
 
  1. module Main where   
  2. import List   
  3.    
  4. inlist [] [] = True   
  5. inlist a [] = False   
  6. inlist a [x] = False   
  7. inlist a (x:nx) = (a == [x, head nx] || a == [head nx, x]) || inlist a nx   
  8. notinlist a b = not (inlist a b)  --不相连判断 
  9.    
  10. permutation [] = [[]]   
  11. permutation xs = [x:ys | x <- xs, ys <- permutation (delete x xs)]  --排列 
  12.    
  13. third list = list!!2 /= 4  --第三位判断,这个硬编码啦 
  14.    
  15. s = [1,2,2,3,4,5]   
  16. res2 = filter (notinlist [3,5]) $ filter third $ nub $ permutation s     
  17. main = print (length res2)  


更新

Erlang在语法上和Haskell有不少类似如list comprehension,pattern match和immutable data,语意上则要简单很多,没有太多新概念比如lazy evaluation:

java 代码
 
  1. fibs = 0 : 1 : [ a + b | (a, b) <- zip fibs (tail fibs)]  

这个使用递归的list comprehension来计算fibonacci数的方法Erlang是没法照搬的,因为fibs是个无限list。

更新2:

新版F#终于也增加了list comprehension,这样在F#可以写成:
java 代码
 
  1. let delete item list = List.filter (fun x -> x <> item) list  
  2.   
  3. let rec permutation x = match x with  
  4.   |[] -> [[]]  
  5.   |xs -> [for x in xs for y in permutation (delete x xs) -> x::ys]  



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值