String 计算字符串中字符的出现次数(Haskell)
可能重复:String 计算字符串中字符的出现次数(Haskell),string,haskell,String,Haskell,可能重复: 给定一个输入字符串,我希望计算每个字符的出现次数。我有两种方法(在帝国伪代码中): 我相信我可以很容易地在Haskell中实现这一点。我的第二个想法有点棘手: For each character in the string increment a counter and store it in a map (or similar data structure) 我对Haskell中的数据结构几乎没有经验,因此第二种解决方案比第一种解决方案更具威胁性。但是,我当然希望通过实现
给定一个输入字符串,我希望计算每个字符的出现次数。我有两种方法(在帝国伪代码中): 我相信我可以很容易地在Haskell中实现这一点。我的第二个想法有点棘手:
For each character in the string
increment a counter and store it in a map (or similar data structure)
我对Haskell中的数据结构几乎没有经验,因此第二种解决方案比第一种解决方案更具威胁性。但是,我当然希望通过实现自己的数据结构或使用内置库中的内容来了解更多信息
有人对我应该如何进行有什么建议吗?
数据。Map
是关联数组的标准。它在容器中
包中,我认为它有很好的文档记录。insertWith
函数可能对此问题特别感兴趣-它允许您插入一个新的键和值,但也提供一个函数(您希望使用+
)将值与映射中已有的值(如果有的话)相结合。数据。映射是关联数组的标准。它在容器中
包中,我认为它有很好的文档记录。insertWith
函数可能对此问题特别感兴趣-它允许您插入一个新的键和值,但也提供了一个函数(您希望使用+
)将值与映射中已有的值(如果有)组合起来。我建议:
- 仔细阅读。折叠是处理列表的函数式编程中非常常见的模式
- 浏览其中的一些(警告:它们涉及面很广,需要一段时间来摸索——但绝对值得付出努力)。像您这样的问题的解决方案通常可以通过将几个预定义函数(例如,sort/group/map/length)粘在一起找到。本练习让您更加熟悉库、Haskell语法和编码风格、FP以及通过组合解决问题
我建议:
- 仔细阅读。折叠是处理列表的函数式编程中非常常见的模式
- 浏览其中的一些(警告:它们涉及面很广,需要一段时间来摸索——但绝对值得付出努力)。像您这样的问题的解决方案通常可以通过将几个预定义函数(例如,sort/group/map/length)粘在一起找到。本练习让您更加熟悉库、Haskell语法和编码风格、FP以及通过组合解决问题
我假设Haskell前奏曲中可能有一个函数(寻找
(等式a,积分I)=>[a]->a->I
),但这可以相当容易地表示为折叠
count a = foldr (\x sum -> if x == a then sum+1 else sum) 0
至于地图,请查看Data.Map模块。(同样,编写一个简单的基于列表的映射也相当容易)我假设Haskell prelude中可能有一个函数(查找(等式a,积分I)=>[a]->a->I
),但这可以相当容易地表示为折叠
count a = foldr (\x sum -> if x == a then sum+1 else sum) 0
至于地图,请查看Data.Map模块。(编写一个简单的基于列表的映射也相当容易)在Haskell中,=
符号与数学中一样用于定义方程。惯用的Haskell避免突变(例如“增加计数器”),而是鼓励使用纯函数的解决方案。然而,使用ST
您可以像在任何其他语言中一样使用变异编写算法
考虑确定单个字符在字符串中出现多少次的任务。
根据你的英文描述
遍历字符串并在找到字符时递增计数器
Python实现将是
def count(c, s):
i = 0
for c0 in s:
if c == c0:
i += 1
return i
使用ST,我们可以编写完全相同的代码,尽管它稍微详细一些,因为所有可变变量的创建、读取和写入都显式命名为:
import Control.Monad (when, forM_)
import Control.Monad.ST (runST)
import Data.STRef
count :: Char -> String -> Int
count c s = runST $ do -- def count(c, s):
i <- newSTRef 0 -- i = 0
forM_ s $ \c' -> do -- for c0 in s:
when (c == c') $ do -- if c == c0:
modifySTRef i (+1) -- i += 1
readSTRef i -- return i
import Control.Monad(when,forM_)
import Control.Monad.ST(runST)
导入数据.STRef
计数::字符->字符串->整数
计数cs=runST$do--def计数(c,s):
i String->Int
在Haskell中,=
符号与数学中一样用于定义方程。惯用的Haskell避免突变(例如“增加计数器”),而是鼓励使用纯函数的解决方案。然而,使用ST
您可以像在任何其他语言中一样使用变异编写算法
考虑确定单个字符在字符串中出现多少次的任务。
根据你的英文描述
遍历字符串并在找到字符时递增计数器
Python实现将是
def count(c, s):
i = 0
for c0 in s:
if c == c0:
i += 1
return i
使用ST,我们可以编写完全相同的代码,尽管它稍微详细一些,因为所有可变变量的创建、读取和写入都显式命名为:
import Control.Monad (when, forM_)
import Control.Monad.ST (runST)
import Data.STRef
count :: Char -> String -> Int
count c s = runST $ do -- def count(c, s):
i <- newSTRef 0 -- i = 0
forM_ s $ \c' -> do -- for c0 in s:
when (c == c') $ do -- if c == c0:
modifySTRef i (+1) -- i += 1
readSTRef i -- return i
import Control.Monad(when,forM_)
import Control.Monad.ST(runST)
导入数据.STRef
计数::字符->字符串->整数
计数cs=runST$do--def计数(c,s):
i String->Int
有一个有趣的单行程序,它以一种完全不同的方式解决了这个问题:首先排序,然后计算同一字符的连续运行次数。(讨论中的一行涉及排序和分组——剩下的就交给你了)@Carl有趣的方法!由于数据是不可变的,原始字符串仍然完好无损。group
和map
和length
对于Carl的方法也很有用。这有一个有趣的一行代码,它以一种完全不同的方式解决了问题:首先排序,然后对同一字符的连续运行进行计数。(讨论中的一行涉及排序和分组——剩下的就交给你了)@Carl有趣的方法!由于数据是不可变的,所以原始字符串仍然是完整的。group
和map
和length
对于C来说很方便