F#Basics:Folding 2列在一起成为一个字符串

时间:2009-12-23 02:05:07

标签: f# functional-programming

从我的Scheme时代开始有点生疏,我想拿两个列表:一个数字和一个字符串,然后将它们折叠成一个字符串,每个字符串写成“{(ushort)5”, bla bla bla“},\ n”。我有大部分内容,我只是不确定如何正确编写折叠:

let splitter = [|","|]
let indexes = 
  indexStr.Split(splitter, System.StringSplitOptions.None) |> Seq.toList 
let values = 
  valueStr.Split(splitter, System.StringSplitOptions.None) |> Seq.toList

let pairs = List.zip indexes values
printfn "%A" pairs

let result = pairs |> Seq.fold
    (fun acc a -> String.Format("{0}, \{(ushort){1}, \"{2}\"\}\n", 
                                acc, (List.nth a 0), (List.nth a 1)))

5 个答案:

答案 0 :(得分:10)

你遗漏了两件事。折叠的初始状态是一个空字符串,你不能在F#中的元组上使用列表理解。

let splitter = [|","|]
let indexes = 
    indexStr.Split(splitter, System.StringSplitOptions.None) |> Seq.toList 
let values = 
    valueStr.Split(splitter, System.StringSplitOptions.None) |> Seq.toList

let pairs = List.zip indexes values
printfn "%A" pairs

let result = 
    pairs 
    |> Seq.fold (fun acc (index, value) -> 
        String.Format("{0}{{(ushort){1}, \"{2}\"}},\n", acc, index, value)) ""

fold2版

let result = 
    List.fold2 
        (fun acc index value -> 
            String.Format("{0}{{(ushort){1}, \"{2}\"}},\n", acc, index, value))
        "" 
        indexes 
        values

如果您关注速度,可能需要使用字符串构建器,因为每次附加时它都不会创建新字符串。

let result = 
    List.fold2 
        (fun (sb:StringBuilder) index value -> 
            sb.AppendFormat("{{(ushort){0}, \"{1}\"}},\n", index, value)) 
        (StringBuilder()) 
        indexes 
        values
    |> string

答案 1 :(得分:8)

折叠可能不是执行此任务的最佳方法。它更容易映射和连接像这样:

let l1 = "a,b,c,d,e".Split([|','|])
let l2 = "1,2,3,4,5".Split([|','|])
let pairs =
    Seq.zip l1 l2
    |> Seq.map (fun (x, y) -> sprintf "(ushort)%s, \"%s\"" x y)
    |> String.concat "\n"

答案 2 :(得分:1)

我想你想要List.fold2。出于某种原因,List模块具有fold2成员,但Seq没有。然后你可以完全免除zip

你的命名变量的类型和你希望的结果类型都是隐含的,所以很难提供帮助,但如果你试图积累一个字符串列表,你可能会考虑一些

let result = pairs |> Seq.fold
  (fun prev (l, r) -> 
          String.Format("{0}, \{(ushort){1}, \"{2}\"\}\n", prev, l, r) 
  "" pairs

我的F#/ Caml非常生疏,所以我可能有错误的参数顺序。还要注意你的弦乐形成是二次的;在我自己的代码中,我会更多地遵循这些方法:

let strings = 
   List.fold2 (fun ss l r -> 
                 String.format ("\{(ushort){0}, \"{1}\"\}\n", l, r) :: ss)
              [] indexes values

let result = String.concat ", " strings

这不会花费你二次时间,而且更容易理解。我已经检查了MSDN,并且相信我在fold2上有正确的参数顺序。

请记住,我知道Caml不是F#,所以我可能有错误的细节或顺序。

答案 3 :(得分:0)

也许这就是:

let strBuilder = new StringBuilder()
for (i,v) in Seq.zip indexes values do
     strBuilder.Append(String.Format("{{(ushort){0}, \"{1}\"}},\n", i,v))
     |> ignore
使用F#有时候更有必要......

答案 4 :(得分:0)

map2或fold2是正确的方法。这是我的看法,使用(||>)运算符:

let l1 = [| "a"; "b"; "c"; "d"; "e" |]
let l2 = [| "1"; "2"; "3"; "4"; "5" |]
let pairs = (l1, l2) ||> Seq.map2 (sprintf ("(ushort)%s, \"%s\""))
                      |> String.concat "\n"