我不知道如何在循环中向自身添加一些字符串。
let parameters = [| [| ("name", "fdjks"); ("value", "dsf") |]; [| ("name", "&^%"); ("value", "helo") |] |] ;;
let boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW";;
let body = "";;
for x = 0 to (Array.length(parameters) : int)-1 do
let (_, paramName) = parameters.(x).(0) in
let (_, paramValue) = parameters.(x).(1) in
body = body ^ "--" ^ boundary ^ "\r\n" ^ "Content-Disposition:form-data; name=\"" ^ paramName ^ "\"\r\n\r\n" ^ paramValue ;
print_endline(body)
done;;
但这会出错。 有什么办法...?
答案 0 :(得分:1)
(^)
运算符连接两个字符串,例如,
# "hello" ^ ", " ^ "world!";;
- : string = "hello, world!"
如果您有一个字符串列表,则可以使用String.concat
函数,该函数带有一个分隔符和一个字符串列表,并以有效的方式在其中产生连接:
# String.concat ", " ["hello"; "world"];;
- : string = "hello, world"
为什么在循环中使用(^)
运算符是一个坏主意?每次合并都会创建一个新字符串,然后将两个字符串的内容复制到新字符串中。因此,追加N
字符串将最终导致大约n^2
的复制(其中n
是字符串的长度)。在Java和其他语言/库中,连接返回一个新的字符串,而不是改变其参数之一,也是如此。通常的解决方案是使用StringBuilder pattern,它在OCaml中用Buffer模块表示。因此,假设您没有String.concat
函数,并且您想构建自己的有效串联函数(这也可能很有用,因为Buffer
比{{1}是更通用的解决方案},并且可以在例如您输入的不是列表时使用)。这是我们的实现,
String.concat
此函数将创建一个缓冲区,该缓冲区将自动调整其大小。 let concat xs =
let buf = Buffer.create 16 in
List.iter (Buffer.add_string buf) xs;
Buffer.contents buf
只是一个初步的猜测,可以是任何数字。在第二行中,我们仅遍历所有字符串并将其推入缓冲区,最后,我们要求缓冲区构建结果字符串。这是我们使用此功能的方式:
16
答案 1 :(得分:0)
在OCaml中,变量默认是不可变的。如果要更改变量的值,则需要使用引用。
let parameters = [| [| ("name", "fdjks"); ("value", "dsf") |]; [| ("name", "&^%"); ("value", "helo") |] |] ;;
let boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW";;
let body = ref "";;
for x = 0 to (Array.length(parameters) : int)-1 do
let (_, paramName) = parameters.(x).(0) in
let (_, paramValue) = parameters.(x).(1) in
body := !body ^ "--" ^ boundary ^ "\r\n" ^ "Content-Disposition:form-data; name=\"" ^ paramName ^ "\"\r\n\r\n" ^ paramValue ;
print_endline(!body)
done;;
另请参阅add elements to list in a loop in OCaml。
请注意,在OCaml中添加两个字符串是O(n)操作(n =字符数),这对于长字符串而言相当昂贵。您可以使用Buffer module有效地连接字符串。但是,使用^
更具可读性。
长时间使用Buffer
模块和对短字符串使用^
可能在可读性和效率之间做出了很好的折衷。因此,为外部迭代使用Buffer是一个好主意。代码如下。
let parameters = [| [| ("name", "fdjks"); ("value", "dsf") |];
[| ("name", "&^%"); ("value", "helo") |] |] ;;
let boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW";;
let body = Buffer.create 256;;
for x = 0 to (Array.length(parameters) : int)-1 do
let (_, paramName) = parameters.(x).(0) in
let (_, paramValue) = parameters.(x).(1) in
Buffer.add_string body
("--" ^ boundary ^ "\r\n"
^ "Content-Disposition:form-data; name=\""
^ paramName ^ "\"\r\n\r\n" ^ paramValue);
print_endline(Buffer.contents body)
done;;
答案 2 :(得分:0)
使用累加器递归迭代是在ocaml中执行所需操作的惯用方式:
let parameters = [| [| ("name", "fdjks"); ("value", "dsf") |]; [| ("name", "&^%"); "value", "helo") |] |] ;;
let boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW" ;;
let len = Array.length(parameters) ;;
let rec loop accum index =
if index < len then
let (_, paramName) = parameters.(index).(0) in
let (_, paramValue) = parameters.(index).(1) in
loop (accum ^ "--" ^ boundary ^ "\r\n"
^ "Content-Disposition:form-data; name=\""
^ paramName ^ "\"\r\n\r\n" ^ paramValue)
(index + 1)
else print_endline accum
in
loop "" 0 ;;
或者最好还是看看Array.fold_left函数。
let parameters = [| [| ("name", "fdjks"); ("value", "dsf") |]; [| ("name", "&^%"); ("value", "helo") |] |] ;;
let boundary = "----WebKitFormBoundary7MA4YWxkTrZu0gW";;
let () = print_endline
(Array.fold_left
(fun acc elt ->
let (_, paramName) = elt.(0) in
let (_, paramValue) = elt.(1) in
acc ^ "--" ^ boundary ^ "\r\n"
^ "Content-Disposition:form-data; name=\""
^ paramName ^ "\"\r\n\r\n" ^ paramValue)
""
parameters)