我正在尝试做一些相当简单的事情。我想取一个字符串,如“1000”,并返回字符串“1000”。
这是我的尝试:
String.map (function x -> if x = ',' then '' else x) "1,000";;
但是我收到编译错误,说有''
感谢您的见解!
答案 0 :(得分:5)
不幸的是,没有像你正在寻找的那个角色。有一个长度为0个字符的字符串(""
),但没有任何字符根本不存在。所有字符(可以这么说)都是1个字符。
要解决您的问题,您需要比String.map
更通用的操作。地图的本质是它的输入和输出具有相同的形状但内容不同。对于字符串,这意味着输入和输出是相同长度的字符串。
除非你真的想避免命令式编码(这实际上是一件很好的事情要避免,特别是在开始使用OCaml时),你最好使用String.iter
和缓冲区(来自{{1}) }模块)。
<强>更新强>
Andreas Rossberg给出的Buffer
函数非常好。这是另一个使用string_map_partial
和缓冲区的实现:
String.iter
只是一种具有不同风格权衡的替代实现。不快,也可能不慢。它仍然是强制性的(出于同样的原因)。
答案 1 :(得分:4)
这里你需要的是一个类似下面的函数,遗憾的是它不在标准库中:
(* string_map_partial : (char -> char option) -> string -> string *)
let string_map_partial f s =
let buf = String.create (String.length s) in
let j = ref 0 in
for i = 0 to String.length s - 1 do
match f s.[i] with
| None -> ()
| Some c -> buf.[!j] <- c; incr j
done;
String.sub buf 0 !j
然后你可以写:
string_map_partial (fun c -> if c = ',' then None else Some c) "1,000"
(注意:我为string_map_partial
选择了一个命令式实现,因为纯函数式实现需要重复的字符串连接,这在OCaml中相当昂贵。)
答案 2 :(得分:0)
纯功能版本可能是这个:
let string_map_partial f s =
let n = String.length s in
let rec map_str i acc =
if i < n then
map_str (i + 1) (acc ^ (f (String.make 1 s.[i])))
else acc
in map_str 0 ""
这是终端递归,但性能不如命令式版本。