这是我的代码:
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>
,我该如何解决?
答案 0 :(得分:3)
元组的最后一个元素是pctrepub
,这是Seq.map
调用的结果,Seq.map
返回序列,而不是数字。因此,元组的最后一个元素是一个序列,这绝对不足为奇。
关于如何解决这个问题,没有足够的信息:我看到你想要获得数字而不是序列,但你不是说数字应该来自哪里,所以我无法帮助你。
答案 1 :(得分:3)
您已经在其他地方提到您是F#的初学者(八天前开始学习它),所以这里有一个快速指南,介绍如何阅读可能有助于您回答一些问题的F#文档这些问题你自己。让我们看一下documentation for the Seq
module。它列出了许多可以在序列上调用的函数: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
只是你实际拥有的任何类型的占位符名称:如果你有整数,这是一个seq<int> -> int
函数。如果你有字符串,这是一个seq<string> -> string
函数,依此类推。 (类型前面的^
字符表示它将在编译时解析,而前面的'
字符表示它将在运行时解析。你赢了需要担心这种区别,直到你对F#有更多的经验,所以现在,只需将其中任何一个视为一个标志,这意味着&#34;这是一个通用类型&#34;)。因此average
函数的类型签名告诉您它需要值序列并返回单个值。
现在,averageBy
。这更复杂。首先,这里有更多的箭头。这与一个名为currying的概念有关,这个概念在链接上得到了很好的解释,所以我不会深入研究它。在初学者级别,您应该将 final 箭头之后的任何内容视为函数的输出,并将所有其余类型作为函数的输入(将由箭头)。换句话说,像int -> char -> string
这样的类型签名应该被理解为&#34;这是一个带有两个输入的函数,先是int
,第二是char
,然后返回{ {1}}&#34;
但是你看到string
类型签名中('T -> ^U)
位周围的括号吗?这些括号意味着他们在数学中的意思:单独阅读这部分内容。因此averageBy
的第一个参数是类型averageBy
。 ('T -> ^U)
的第二个参数的类型为averageBy
,输出的类型为seq<'T>
。现在,如果您查看类型签名^U
,它中有一个箭头,因此它是一个函数。具体来说,它是一个采用泛型类型('T -> ^U)
的函数并返回泛型类型T
的函数。 (正如我之前所说,现在不要担心U
与'
的区别。第二个参数是类型^
的项序列,输出类型为T
。该类型签名加上名称,为您提供了关于函数如何工作的线索:它将查看U
类型的事物序列,并且对于每个类型,它将调用函数来转换T
。 1}}成为T
类型的东西。然后它返回一个U
值作为输出:从名称中,您可以得出结论,它返回的单个值将是U
函数生成的所有U
值的平均值
所以类型签名'T -> ^U
意味着第一个参数是一个带('T -> ^U) -> seq<'T> -> ^U
并返回T
的函数,第二个参数是{{1}类型的项目序列该函数返回一个U
类型的单项。
最后,让我们看一下T
。它的类型签名看起来与U
非常相似:第一个参数也是一个带map
并将其转换为averageBy
的函数。第二个参数也是T
项的序列。但是这一次U
的结果不是单个值,而是T
值的序列。
因此,通过查看documentation,我们可以看到,如果您不希望序列作为输出,map
是错误的调用。 U
模块中有一个令人眼花缭乱的功能列表,所以您可能会感到有点不知所措。但是仔细查看类型签名,并了解每个签名的含义,对于确定哪个签名将根据您的数据执行您想要的操作有很大帮助。阅读https://fsharpforfunandprofit.com/posts/list-module-functions/也将对您有很大帮助:F#认真对待Seq.map
,Seq
和List
模块,因为非常相似,包括几乎所有相同的功能。因此,如果您知道Seq
的作用,您也会知道Array
和List.averageBy
的作用:唯一的区别在于它们作为输入采用何种类型的集合。因此即使该页面讨论了列表,它的建议也适用于Seq。
有人已在评论中回答了您的问题(只需执行Seq.averageBy
,您应该得到您想要的结果),因此我不会在那里详细介绍。希望我花时间写这篇文章对你帮助你更深入地理解事情是有用的,这样你就可以在将来回答你自己的问题并且不必依赖于在Stack Overflow上提问。 (然后等待,有时是几个小时,以获得答案)。