List F#:如何打印完整列表(Console.WriteLine()只打印前三个元素)

List F#:如何打印完整列表(Console.WriteLine()只打印前三个元素),list,f#,List,F#,是否可以不使用循环打印完整列表? 我试过: 它只打印三个第一元素: [1;2;3; ... ] 不,不使用循环/循环排序就无法打印F#列表的内容。要打印每个元素,必须枚举每个元素 在F#中,虽然不需要使用循环,但可以使用漂亮的管道操作来完成 [1;2;3;4;5] |> Seq.iter (fun x -> printf "%d " x) 正如朱丽叶所指出的,我可以通过部分应用进一步简化这个过程 [1;2;3;4;5] |> Seq.iter (printf "%d ")

是否可以不使用循环打印完整列表? 我试过:

它只打印三个第一元素:

[1;2;3; ... ]

不,不使用循环/循环排序就无法打印F#列表的内容。要打印每个元素,必须枚举每个元素

在F#中,虽然不需要使用循环,但可以使用漂亮的管道操作来完成

[1;2;3;4;5] |> Seq.iter (fun x -> printf "%d " x)
正如朱丽叶所指出的,我可以通过部分应用进一步简化这个过程

[1;2;3;4;5] |> Seq.iter (printf "%d ")

如果您想使用内置的F#格式化引擎(并避免自己实现相同的功能),可以使用F#打印功能,如
printfn
。您可以给它一个格式说明符来打印整个列表(使用F#格式)或只打印前几个元素(当您调用
ToString
时会发生这种情况):

如果出于某种原因要使用
Console.WriteLine
(或其他.NET方法),也可以使用
sprintf
,其行为类似于
printf
,但返回格式化字符串作为结果:

Console.WriteLine(sprintf "%A" list)

使用
printf
sprintf
的好处是,它还可以自动处理其他F类型(例如,如果您有一个包含元组、有区别的联合或记录的列表)。

一种可能更实用的方法:

let nums = [1;2;3;4;5;6]
let concat acc x = acc + " " + (string x)
let full_list = List.fold concat "" nums
printfn "%s" full_list

通常,如果要更改printf“%a”将对象打印为fsi.exe显示类型值的方式,可以对类型应用StructuredFormatDisplayaAttribute属性:

[<StructuredFormatDisplayAttribute("PP {PrettyPrinter}")>]
type Foo(a:string array) =
  let pp = Array.mapi (fun i (s: string) -> sprintf "{idx: %d len: %d contents: '%s'}" i s.Length s) a
  member x.PrettyPrinter = pp

> let foo = Foo [|"one";"two";"three"|];;
val foo : Foo =
  PP [|"{idx: 0 len: 3 contents: 'one'}"; "{idx: 1 len: 3 contents: 'two'}";
       "{idx: 2 len: 5 contents: 'three'}"|]

> printfn "%A" foo;;
PP [|"{idx: 0 len: 3 contents: 'one'}"; "{idx: 1 len: 3 contents: 'two'}";
     "{idx: 2 len: 5 contents: 'three'}"|]
val it : unit = ()
[]
类型Foo(a:字符串数组)=
让pp=Array.mapi(fun i(s:string)->sprintf“{idx:%d len:%d contents:'%s'}”i s.Length s)a
成员x.PrettyPrinter=pp
>设foo=foo[|“一”、“二”、“三”];;
瓦尔福:福=
PP[|“{idx:0 len:3 contents:'1'}”;“{idx:1 len:3 contents:'2'}”;
“{idx:2 len:5 contents:'三'}”|]
>printfn“%A”foo;;
PP[|“{idx:0 len:3 contents:'1'}”;“{idx:1 len:3 contents:'2'}”;
“{idx:2 len:5 contents:'三'}”|]
val it:unit=()

也许这个答案能帮你解决-
[1;2;3;4;5]|>Seq.iter(printf“%d”)
--w00t,currying:)
对于[1;2;3;4;5]中的x,执行printf“%d”x
-我实际上认为简单for循环和
Seq.iter
一样好。当然要看情况而定,但在某些情况下,我个人更喜欢直截了当(也许更迫切?)的解决方案。如果不可能,这是否意味着托马斯·佩特里切克的答案是错误的?@abatischev,@Tomas的答案肯定是正确的,而且功能正常,但是在后台出现了一个循环来打印元素,它只是不在实际的答案代码中。@Juliet实际上不是在使用curry,而是部分应用程序:)不幸的是,字符串连接在.NET上的操作效率非常低(因为它需要复制整个字符串),因此,对于大型列表,这可能会有糟糕的性能。在.NET中,推荐的方法是使用
StringBuilder
(这是可变的,使解决方案的功能有所降低),
List.fold\u left
称为
List.fold
,您可以用重载的
string
函数替换
string\u的int
。更新以匹配Tomas的注释。这种语言最近变化太快,有点难以跟上。是的,尤其是命名!然而,现在F#是visualstudio2010的一部分(它几乎已经完成了),不会有太多的变化(在语言和核心库中)。很有趣。pretty printer函数需要是公共成员吗?@Joel——这并不重要,因为该属性是通过引用APII获得的。我注意到带有seq%a的“%a”不会打印整个列表:
printf“%a”[1..500]停留在
100
@Clément我怀疑这可能在过去7年的某个时候发生了变化:-)。我不这么认为:)但是,在2009年,它已经错了(参见例如,其中提到了这个问题)。看起来你是对的。总是有
list |>list.map(sprintf“%A”)|>String.concat“,“|>sprintf”[%s]”
let nums = [1;2;3;4;5;6]
let concat acc x = acc + " " + (string x)
let full_list = List.fold concat "" nums
printfn "%s" full_list
[<StructuredFormatDisplayAttribute("PP {PrettyPrinter}")>]
type Foo(a:string array) =
  let pp = Array.mapi (fun i (s: string) -> sprintf "{idx: %d len: %d contents: '%s'}" i s.Length s) a
  member x.PrettyPrinter = pp

> let foo = Foo [|"one";"two";"three"|];;
val foo : Foo =
  PP [|"{idx: 0 len: 3 contents: 'one'}"; "{idx: 1 len: 3 contents: 'two'}";
       "{idx: 2 len: 5 contents: 'three'}"|]

> printfn "%A" foo;;
PP [|"{idx: 0 len: 3 contents: 'one'}"; "{idx: 1 len: 3 contents: 'two'}";
     "{idx: 2 len: 5 contents: 'three'}"|]
val it : unit = ()