[英]Why output is <seq> and not int in F#?
这是我的代码:
Csv.GetSample().Rows
|> Seq.groupBy (fun row -> row.STATE,row.INCOME,row.CHILDREN)
|> Seq.map (fun ((state,income,children),data) ->
let pctrepub = data|> Seq.map (fun row -> (100.0 - float row.otherparty))
((state,income,children),pctrepub))
|> List.ofSeq
这是我理想的结果:
(("TX", "51522", "0"), 65.0);
(("AL", "6481", "1"), 51.4);
(("MO", "78921", "1"), 25.1);
(("TN", "12000", "4"), 62.1);
(("PA", "79850", "2"), 41.2);
(("NY", "79215", "1"), 31.0);
(("CA", "79045", "2"), 50.5);
这就是我最终得到的结果:
(("TX", "51522", "0"), <seq>);
(("AL", "6481", "1"), <seq>);
(("MO", "78921", "1"), <seq>);
(("TN", "12000", "4"), <seq>);
(("PA", "79850", "2"), <seq>);
(("NY", "79215", "1"), <seq>);
(("CA", "79045", "2"), <seq>);
为什么最后一行值显示为<seq>
,我该如何解决?
元组的最后一个元素是pctrepub
,这是Seq.map
调用的结果,并且Seq.map
返回一个序列,而不是数字。 因此,元组的最后一个元素是序列绝对不奇怪。
关于如何解决此问题,没有足够的信息:我看到您想获取数字而不是序列,但是您并不是在说数字应该从哪里来,所以我无法为您提供帮助。
您在其他地方提到过,您是F#的初学者(八天前开始学习它),因此,这是如何阅读F#文档的快速指南,它可以帮助您自己回答其中的一些问题。 让我们看一下Seq
模块的文档 。 它列出了许多可以在序列上调用的函数: append
, average
, averageBy
, filter
, map
, groupBy
…它们都有不同的类型签名,每个函数的类型签名都是其作用的线索。 让我们看几个例子:
average
: seq<^T> -> ^T
返回序列中元素的平均值。 averageBy
:( ('T -> ^U) -> seq<'T> -> ^U
返回通过将函数应用于序列的每个元素而生成的结果的平均值。 map
:( ('T -> 'U) -> seq<'T> -> seq<'U>
-创建一个新集合,其元素是将给定功能应用于集合的每个元素的结果。 首先, average
,因为它是最简单的。 类型标记中的->
箭头告诉您这是一个函数。 输入在箭头的左边,输出在箭头的右边。 因此,该类型签名意味着此函数采用seq<^T>
并返回^T
类型的项。 类型名称T
前面的^
或'
字符表示它是通用类型,它将在运行代码时解析为您实际拥有的任何类型:int,字符串,元组等。 因此, T
只是您实际拥有的任何类型的占位符名称:如果您有int,则这是seq<int> -> int
函数。 如果您有字符串,这是seq<string> -> string
函数,依此类推。 (类型前面的^
字符表示将在编译时进行解析,而类型前面的'
字符表示将在运行时进行解析。在您完成此操作之前,无需担心这种区别。在F#方面有更多的经验,所以现在,只需将其中一个当作标志,就意味着“这是一个通用类型”)。 因此, average
函数的类型签名告诉您,它采用一系列值并返回一个值 。
现在, averageBy
。 这更加复杂。 首先,这里还有更多箭头。 这与一个名为currying的概念有关,在链接上对此解释得很好,因此我不会深入探讨。 在初学者级别,您应该将最后一个箭头之后的内容视为函数的输出,并将所有其他类型视为函数的输入(将由箭头分隔)。 换句话说,类型签名(例如int -> char -> string
应被理解为“这是一个需要两个输入的函数,首先输入int
,然后输入char
,然后返回string
。”
但是,您是否在averageBy
类型签名中的('T -> ^U)
位周围看到括号? 这些括号的含义与数学含义相同:请单独阅读本部分。 因此, averageBy
的第一个参数是类型('T -> ^U)
。 averageBy
的第二个参数的类型为seq<'T>
,输出的类型为^U
现在,如果您查看类型签名('T -> ^U)
,它上面有一个箭头,因此它是一个函数。 具体来说,它是一个函数,它接受通用类型T
的东西,并返回通用类型U
的东西。 (正如我之前说的,现在不必担心'
vs. ^
区别)。 第二个参数是T
类型的项目序列,输出是U
类型。 该类型签名加上名称,为您提供有关函数工作方式的线索:它将查看类型T
的事物序列,对于每个事物,它将调用该函数将T
事物转换为事物。输入U
然后,它返回一个U
值作为输出:从名称中可以得出结论,它返回的单个值将是'T -> ^U
函数产生的所有U
值的平均值。
因此,类型签名('T -> ^U) -> seq<'T> -> ^U
表示第一个参数是一个接受T
并返回U
的函数,第二个参数是一个类型为null的项目序列T
,并且该函数返回单个类型U
项目。
最后,让我们看一下map
。 它的类型签名看起来与averageBy
非常相似:第一个参数还是一个接受T
并将其转换为U
的函数。 第二个参数还是T
项的序列。 但是这次, map
的结果将是一系列 U
值,而不是单个值。
因此,通过查看文档 ,我们可以看到,如果您不希望将序列作为输出,则调用Seq.map
是错误的事情。 Seq
模块中的函数列表令人迷惑,因此您可能会觉得不知所措。 但是仔细查看类型签名,并理解每个签名的含义,对于确定哪个签名可以满足您的数据需求将大有帮助。 并且通读https://fsharpforfunandprofit.com/posts/list-module-functions/对您也有很大帮助:F#将List
, Seq
和Array
模块视为彼此极其相似 ,包括几乎所有相同的功能。 因此,如果您知道List.averageBy
功能,那么您还将知道Seq.averageBy
和Array.averageBy
功能:唯一的区别在于它们将哪种类型的集合用作输入。 因此,即使该页面讨论列表,它的建议也适用于Seq。
有人已经在评论中回答了您的问题(只需执行Seq.map (fun row -> (row.STATE,row.INCOME,row.CHILDREN), 100.0 - float row.otherparty)
,您就应该得到想要的结果) ,因此我在这里不再赘述。 希望我花时间写这篇文章将对您有所帮助,以帮助您更深入地理解事物,以便您将来可以回答自己的问题,而不必太依赖于对Stack Overflow的询问(和然后等待,有时需要几个小时才能找到答案)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.