如何将列表推导式实现的大写字母计数函数改写为map实现?
用map实现大写字母统计函数
你现有的函数可以统计输入字符串中A-Z每个大写字母的出现次数,返回一个长度为26的列表(比如输入"ABCd"会返回[1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])。当前用列表推导式实现,但要求改用map函数完成,具体操作如下:
原实现代码
counter xs = [count x xs |x<- ['A'..'Z']] where count x [] = 0 count a (x:xs) |a == x = 1 + count a xs |otherwise = count a xs
改用map的实现方式
你的count函数的作用是统计单个字符在目标列表中的出现次数,而map的核心就是将一个函数批量应用到列表的每个元素上,刚好可以替代列表推导式的遍历逻辑:
基础改写版本
直接把原本对每个字母执行的count x xs包装成匿名函数,传给map:
counter xs = map (\c -> count c xs) ['A'..'Z'] where count x [] = 0 count a (x:xs) |a == x = 1 + count a xs |otherwise = count a xs
柯里化简化版本
利用Haskell的柯里化特性,把count和xs绑定后得到一个仅接收单个字母的函数,直接传给map,代码更简洁:
counter xs = map (`count` xs) ['A'..'Z'] where count x [] = 0 count a (x:xs) |a == x = 1 + count a xs |otherwise = count a xs
利用标准库简化(可选)
Haskell的Data.List模块提供了filter函数,结合length可以替代你手写的count函数,进一步简化代码:
import Data.List (filter) counter xs = map (\c -> length $ filter (==c) xs) ['A'..'Z']
或者再用柯里化优化:
import Data.List (filter) counter xs = map (length . flip filter xs . (==)) ['A'..'Z']
内容的提问来源于stack exchange,提问作者immi0815
相关产品推荐
相关产品推荐

