Haskell中map/filter/zip以及fodlr来实现功能的例子

Haskell中map/filter/zip以及fodlr来实现功能的例子

功能名findIndex
type定义是(a -> Bool) -> [a] -> Maybe Int
函数 find 返回满足谓词的列表的第一个元素,如果没有这样的元素,则返回 Nothing。 findIndex 返回对应的索引。 findIndices 返回所有此类索引的列表。
例子:
Input: findIndex (>3) [0,2,4,6,8]
Output: Just 2

double1 ::  [Int]
double1 = map f evenList
        where f z = z^2 
evenList :: [Int] 
evenList = filter even [1..20]
还有另一种方式
evenm = map (^2) (filter even [1..20])

第二种更简洁方便.
所以map后面跟运算符号, filter后面跟限制要求和范围,或者filter 后面跟其他功能+范围

pyths :: Int -> [(Int, Int, Int)]
pyths n = 
[(a,b,c)|a <- [1..n], b<- [1..n],c <- [1..n],a^2 +b^2 == c^2]

这种[]的基本模板是,首先把结果放在最前面比如这里的(a,b,c)然后用分割线隔开, 把每个成分的范围说明,最后才是三者之间的联系

findIndices :: (Num a, Enum a) => (t -> Bool) -> [t] -> [a]
findIndices _ [] = []
findIndices p xs = [ i | (x,i) <- zip xs [0..], p x]

--indice 和indices 本质上是一样的都能得出正确结果
indice :: (Num a1, Enum a1, Eq a2) => a2 -> [a2] -> [a1]
indice a xs = [i |(x,i) <- zip xs [0..], a == x]
indices :: Eq a => a -> [a] -> [Int]
indices x xs = [ n | (v, n) <- zip xs [0..], v == x ]

filter 和[]能够起到一样的作用

records = [(True,5), (False,7), (True,12), (True,8),(False,15), (True,4)]

choose2 :: [(Bool, Integer)]
choose2 =[(x,y) |(x,y) <- records,  x==True &&y<10 ]
choose1 :: [(Bool, Integer)]
choose1 = filter (\ (p,n) -> p && n < 10) records

这里(p,n) -> p 就代表了p是True的情况,如果想要代表False那么只需要加一个not变成以下这样(p,n) -> not p

本质上其实就是在做map 和filter

nine :: [Int] -> [Int]
nine [] = []        
nine (x:xs)
        |x >= 9 =(x-9):nine (xs)
        |otherwise = x:(nine xs)

double :: Num a => a -> a
double x = x*2
luhnDouble :: (Ord a, Num a) => a -> a
luhnDouble a
        |double a < 9 = double a
        |double a >=9 = (double a)-9


factorial :: Int -> Int
factorial 0 = 1
factorial n
 | n > 0 = n * factorial (n-1)
 | otherwise = error "Input must be positive"
 
fact n = product [1..n]
fact2 0 =1
fact2 n = n * (fact2(n-1))

nfact n = product [n..(-1)]
nfact2 n = n * (fact2(n+1))

当还没学print的适合error这样表示

euclid :: Int -> Int -> Int
euclid n1 n2
 | n1 == n2 = n1
 | n1 > n2 = euclid (n1-n2) n2
 | otherwise = euclid n1 (n2-n1)
 
com :: Int -> Int -> Int
com m n = 
  let c = min m n 
      st = [ x | x <- [c,c-1 .. 1], m `mod` x == 0 && n `mod` x == 0]
  in head st

let in 也可以实现找到最大共因数

gradeBands :: [(String, Int)] -> (Int,Int,Int,Int,Int,Int)
gradeBands marks
 = (count filter1, count filter2, count filter3,
 count filter4, count filter5, count filter6)
 where
 filter1 n = n < 30
 filter2 n = n >= 30 && n < 40
 filter3 n = n >= 40 && n < 50
 filter4 n = n >= 50 && n < 60
 filter5 n = n >= 60 && n < 70
 filter6 n = n >= 70
 count filter
 = length [ name | (name,grade) <- marks, filter grade]

当filter的东西比较多时,这是一个很好的例子

zip1 :: [Int] -> String -> [(Int,String)]
zip1 m n = zip m (toChar n)

toChar :: String -> [String]
toChar s = map (\c -> [c]) s


zip' :: [a] -> [b] -> [(a,b)]
zip' [] _ = []
zip' _ [] = []
zip' (a:as) (b:bs) = (a,b) : zip' as bs

运行后得到的结果跟输入的结果完全一致

same xs = foldr (++) [] (map sing xs)
            where
            sing x = [x]

sortvalue整理任意两个通过其包含的大小,而sort 是整理整个list让它从小到大的排序

sortvalue :: (String, Int) -> (String, Int) -> Bool
sortvalue (_,g1) (_,g2) = g1 <= g2

sort :: [Int] -> [Int]
sort [] = []
sort [x] = [x]
sort (x:xs) = sort smaller ++ [x] ++ sort larger
  where
    smaller = filter (<= x) xs
    larger = filter (> x) xs

maximum’是使用其中一种折叠函数实现最大的功能。

maximum’ xs = foldl (max) xs

max1 :: [Int] -> Int
max1 []= 0
max1 [x] = x
max1 (x:xs) 
    |(max1 xs) > x = max1 xs
    |otherwise = x

map 和 filter 可以转换成 list comprehensions
总结以下: 通过map 里面的变化或者算法得到的结果放在list comprehension 的 | 前面,如果没有map 那么就默认只有x.
!!注意顺序map 和 filter 的前后不同,同一个公式的结果可能不同

(a) map (+3) xs
[x+3 | x <- xs]
(b) filter (>7) xs
[x | x <- xs, x>7]
(c) concat (map (\x -> map (\y -> (x,y)) ys) xs)
[(x,y) | x<-xs, y<-ys]
(d) filter (>3) (map (\(x,y) -> x+y) xys)
[ x+y | (x,y) <- xys, (x+y) > 3 ]

使用 foldr 重新定义地图 f 和过滤器 p
这个特别重要,一定要记住

map' f = foldr ((:).f) []
filter' p = foldr (\x xs -> if p x then x : xs else xs) []
--OR
filter'' p = foldr (\x -> if (p x) then (x:) else id) []
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值