简体   繁体   English

为什么输出是 <seq> 而不是int in F#?

[英]Why output is <seq> and not int in F#?

This is my code: 这是我的代码:

 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

This is my ideal result: 这是我理想的结果:

   (("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);

This is what I am ending up with: 这就是我最终得到的结果:

   (("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>);

Why is the last row of values appearing as <seq> and how do I fix this? 为什么最后一行值显示为<seq> ,我该如何解决?

The last element of the tuple is pctrepub , which is the result of a Seq.map call, and Seq.map returns a sequence, not a number. 元组的最后一个元素是pctrepub ,这是Seq.map调用的结果,并且Seq.map返回一个序列,而不是数字。 So it's absolutely no surprise that the last element of the tuple is a sequence. 因此,元组的最后一个元素是序列绝对不奇怪。

As to how to fix this, there is not enough information: I see that you want to get number instead of sequences, but you're not saying where the numbers should come from, so I can't help you there. 关于如何解决此问题,没有足够的信息:我看到您想获取数字而不是序列,但是您并不是在说数字应该从哪里来,所以我无法为您提供帮助。

You've mentioned elsewhere that you're a beginner at F# (started learning it eight days ago), so here's a quick guide to how to read the F# documentation that might help you answer some of these questions yourself. 您在其他地方提到过,您是F#的初学者(八天前开始学习它),因此,这是如何阅读F#文档的快速指南,它可以帮助您自己回答其中的一些问题。 Let's look at the documentation for the Seq module . 让我们看一下Seq模块文档 It lists a lot of functions that can be called on sequences: append , average , averageBy , filter , map , groupBy ... They all have different type signatures, and the type signature of each function is a clue to what it will do. 它列出了许多可以在序列上调用的函数: appendaverageaverageByfiltermapgroupBy …它们都有不同的类型签名,每个函数的类型签名都是其作用的线索。 Let's look at a few examples: 让我们看几个例子:

  • average : seq<^T> -> ^T - Returns the average of the elements in the sequence. averageseq<^T> -> ^T返回序列中元素的平均值。
  • averageBy : ('T -> ^U) -> seq<'T> -> ^U - Returns the average of the results generated by applying the function to each element of the sequence. averageBy :( ('T -> ^U) -> seq<'T> -> ^U返回通过将函数应用于序列的每个元素而生成的结果的平均值。
  • map : ('T -> 'U) -> seq<'T> -> seq<'U> - Creates a new collection whose elements are the results of applying the given function to each of the elements of the collection. map :( ('T -> 'U) -> seq<'T> -> seq<'U> -创建一个新集合,其元素是将给定功能应用于集合的每个元素的结果。

First, average , since it's simplest. 首先, average ,因为它是最简单的。 The -> arrow in the type signure tells you that this is a function. 类型标记中的->箭头告诉您这是一个函数。 The input is left of the arrow, and the output is right of the arrow. 输入在箭头的左边,输出在箭头的右边。 So that type signature means this function takes a seq<^T> and returns an item of type ^T . 因此,该类型签名意味着此函数采用seq<^T>并返回^T类型的项。 The ^ or ' characters in front of the type name T mean that it's a generic type, which will resolve to whatever type you actually have when you run the code: int, string, a tuple, whatever. 类型名称T前面的^'字符表示它是通用类型,它将在运行代码时解析为您实际拥有的任何类型:int,字符串,元组等。 So T is just a placeholder name for whatever type you actually have: if you have ints, this is a seq<int> -> int function. 因此, T只是您实际拥有的任何类型的占位符名称:如果您有int,则这是seq<int> -> int函数。 If you have strings, this is a seq<string> -> string function, and so on. 如果您有字符串,这是seq<string> -> string函数,依此类推。 (The ^ character in front of the type means that it will be resolved at compile-time, whereas a ' character in front means it will be resolved at run-time. You won't need to worry about this distinction until you've had a lot more experience with F#, so for now, just treat either one of these as a flag that means "This is a generic type"). (类型前面的^字符表示将在编译时进行解析,而类型前面的'字符表示将在运行时进行解析。在您完成此操作之前,无需担心这种区别。在F#方面有更多的经验,所以现在,只需将其中一个当作标志,就意味着“这是一个通用类型”)。 So the type signature of the average function tells you that it takes a sequence of values and returns a single value . 因此, average函数的类型签名告诉您,它采用一系列值并返回一个值

Now, averageBy . 现在, averageBy This is more complicated. 这更加复杂。 First, there are more arrows here. 首先,这里还有更多箭头。 This is related to a concept called currying , which is explained very well at the link so I won't dive into it. 这与一个名为currying的概念有关,在链接上对此解释得很好,因此我不会深入探讨。 At the beginner level, you should think of whatever comes after the final arrow as being the output of the function, and all the rest of the types as being the inputs of the function (which will be separated by arrows). 在初学者级别,您应该将最后一个箭头之后的内容视为函数的输出,并将所有其他类型视为函数的输入(将由箭头分隔)。 In other words, a type signature like int -> char -> string should be read as "this is a function that takes two inputs, an int first and a char second, and returns a string ." 换句话说,类型签名(例如int -> char -> string应被理解为“这是一个需要两个输入的函数,首先输入int ,然后输入char ,然后返回string 。”

But do you see the parentheses around the ('T -> ^U) bit in the averageBy type signature? 但是,您是否在averageBy类型签名中的('T -> ^U)位周围看到括号? Those parentheses mean just what they mean in math: read this part in isolation. 这些括号的含义与数学含义相同:请单独阅读本部分。 So the first parameter of averageBy is something of type ('T -> ^U) . 因此, averageBy的第一个参数是类型('T -> ^U) The second parameter of averageBy is of type seq<'T> , and the output is of type ^U . averageBy的第二个参数的类型为seq<'T> ,输出的类型为^U Now if you look at the type signature ('T -> ^U) , it has an arrow in it, so it's a function. 现在,如果您查看类型签名('T -> ^U) ,它上面有一个箭头,因此它是一个函数。 Specifically, it's a function that takes a thing of generic type T and returns a thing of generic type U . 具体来说,它是一个函数,它接受通用类型T的东西,并返回通用类型U的东西。 (As I said earlier, don't worry about the ' vs. ^ distinction right now). (正如我之前说的,现在不必担心' vs. ^区别)。 The second parameter is a sequence of items of type T , and the output is of type U . 第二个参数是T类型的项目序列,输出是U类型。 That type signature, plus the name, gives you a clue as to how the function works: it will look through the sequence of things of type T , and for each one, it will call the function to convert that T thing into a thing of type U . 该类型签名加上名称,为您提供有关函数工作方式的线索:它将查看类型T的事物序列,对于每个事物,它将调用该函数将T事物转换为事物。输入U Then it returns a single U value as the output: from the name, you can conclude that the single value it returns will be the average of all the U values produced by the 'T -> ^U function. 然后,它返回一个U值作为输出:从名称中可以得出结论,它返回的单个值将是'T -> ^U函数产生的所有U值的平均值。

So the type signature ('T -> ^U) -> seq<'T> -> ^U means that the first argument is a function that takes a T and returns a U , the second argument is a sequence of items of type T , and the function returns a single item of type U . 因此,类型签名('T -> ^U) -> seq<'T> -> ^U表示第一个参数是一个接受T并返回U的函数,第二个参数是一个类型为null的项目序列T ,并且该函数返回单个类型U项目。

Finally, let's look at map . 最后,让我们看一下map Its type signature looks rather similar to averageBy : the first parameter is again a function that takes a T and converts it to a U . 它的类型签名看起来与averageBy非常相似:第一个参数还是一个接受T并将其转换为U的函数。 The second parameter is again a sequence of T items. 第二个参数还是T项的序列。 But this time, instead of a single value, the result of map will be a sequence of U values. 但是这次, map的结果将是一系列 U值,而不是单个值。

And so, by looking at the documentation , we can see that if you don't want a sequence as output, Seq.map is the wrong thing to call. 因此,通过查看文档 ,我们可以看到,如果您不希望将序列作为输出,则调用Seq.map是错误的事情。 There's a bewildering list of functions in the Seq module, so you might feel a bit overwhelmed. Seq模块中的函数列表令人迷惑,因此您可能会觉得不知所措。 But carefully looking at the type signatures, and understanding what each one means, is a big help in figuring out which one will do what you want with your data. 但是仔细查看类型签名,并理解每个签名的含义,对于确定哪个签名可以满足您的数据需求将大有帮助。 And reading through https://fsharpforfunandprofit.com/posts/list-module-functions/ will be a big help to you too: F# carefully treats the List , Seq and Array modules as extremely similar to each other , including having almost all the same functions. 并且通读https://fsharpforfunandprofit.com/posts/list-module-functions/对您也有很大帮助:F#将ListSeqArray模块视为彼此极其相似 ,包括几乎所有相同的功能。 So if you know what List.averageBy does, you will also know what Seq.averageBy and Array.averageBy do as well: the only difference will be in what type of collection they take as input. 因此,如果您知道List.averageBy功能,那么您还将知道Seq.averageByArray.averageBy功能:唯一的区别在于它们将哪种类型的集合用作输入。 So even though that page talks about lists, its advice also applies to Seq as well. 因此,即使该页面讨论列表,它的建议也适用于Seq。

Someone has already answered your question in the comments (just do Seq.map (fun row -> (row.STATE,row.INCOME,row.CHILDREN), 100.0 - float row.otherparty) and you should get the result you want), so I won't go into more details there. 有人已经在评论中回答了您的问题(只需执行Seq.map (fun row -> (row.STATE,row.INCOME,row.CHILDREN), 100.0 - float row.otherparty) ,您就应该得到想要的结果) ,因此我在这里不再赘述。 Hopefully the time I spent to write this will be useful to you in helping you understand things in more depth, so that you can answer your own questions in the future and won't have to be quite as reliant on asking on Stack Overflow (and then waiting, sometimes hours, for the answers). 希望我花时间写这篇文章将对您有所帮助,以帮助您更深入地理解事物,以便您将来可以回答自己的问题,而不必太依赖于对Stack Overflow的询问(和然后等待,有时需要几个小时才能找到答案)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM