[英]F# pipelines and LINQ
I'm starting to learn F#. 我开始学习F#。 I'm finding quite dificult to change my mind from OO programing. 我发现很难从OO编程中改变主意。 I would like to know how would a F# developer write the following: 我想知道F#开发人员将如何编写以下内容:
"Traditional" C# “传统” C#
public List<List<string>> Parse(string csvData){
var matrix = new List<List<string>>();
foreach(var line in csvData.Split(Environment.NewLine.ToArray(), StringSplitOptions.None)){
var currentLine = new List<string>();
foreach(var cell in line.Split(','){
currentLine.Add(cell);
}
matrix.Add(currentLine);
}
return matrix;
}
"Functional" C# “功能性” C#
public List<List<string>> Parse(string csvData){
return csvData.Split(Environment.NewLine.ToArray(), StringSplitOptions.None).Select(x => x.Split(',').ToList()).ToList();
}
The Question is: Would the code below considered right? 问题是: 下面的代码是否正确?
F# F#
let Parse(csvData:string) =
csvData.Split(Environment.NewLine.ToArray(), StringSplitOptions.None).ToList()
|> Seq.map(fun x -> x.Split(',').ToList())
Your translation looks good to me. 您的翻译对我来说看起来不错。 The use of extension method in C# (such as foo.Select(...)
) is roughly equivalent to the use of pipeline and F# function from List
, Seq
or Array
modules, depending on which collection type you're using (eg foo |> Seq.map (...)
). 在C#中使用扩展方法(例如foo.Select(...)
)大致等同于使用List
, Seq
或Array
模块中的管道和F#函数,具体取决于所使用的集合类型(例如foo |> Seq.map (...)
)。
It is perfectly fine to use LINQ extension methods from F# and mix them with F# constructs, but I would only do that when there is no corresponding F# function, so I would probably avoid ToArray()
and ToList()
in the sample and write: 可以使用来自F#的LINQ扩展方法并将它们与F#构造混合使用,这是完全可以的,但是我只会在没有相应的F#函数的情况下这样做,因此我可能会避免在示例中使用ToArray()
和ToList()
并编写:
open System
let Parse(csvData:string) =
// You can pass the result of `Split` (an array) directly to `Seq.map`
csvData.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.None)
// If you do not want to get sequence of arrays (but a sequence of F# lists)
// you can convert the result using `Seq.toList`, but I think working with
// arrays will be actually easier when processing CSV data
|> Seq.map(fun x -> x.Split(',') |> Seq.toList)
There are a few things not very F#-ish in your solution: 您的解决方案中有一些不是F#的东西:
List
is named ResizeArray in F# and they don't have good support as built-in collections including Array, List, Seq. 可变List
在F#中被命名为ResizeArray ,并且它们作为内置集合(包括Array,List,Seq)没有很好的支持。 Changing the return type to string [] []
, you could make more succinct code with a helper function: 将返回类型更改为string [] []
,您可以使用辅助函数使代码更简洁:
let split (delim: string) (str: string) =
str.Split([|delim|], StringSplitOptions.RemoveEmptyEntries)
let parse (csvData: string) =
csvData
|> split Environment.NewLine
|> Array.map (split ",")
There are subtle differences between the various solutions on this page. 本页上的各种解决方案之间有细微的差异。 For example, your C# solutions and pad's solution are eager, but your F# version and Tomas' are lazy. 例如,您的C#解决方案和pad的解决方案很渴望,但是F#版本和Tomas'却很懒。 Yours and pad's split on Environment.NewLine
, but Tomas' splits on any char in NewLine
(I'm guessing you want the latter since you called the overload that accepts StringSplitOptions
). 您和pad在Environment.NewLine
上拆分,但Tomas在NewLine
任何 char上NewLine
(我猜您想要后者,因为您调用了接受StringSplitOptions
的重载)。 Maybe these matter; 也许这些很重要; maybe not. 也许不吧。
Anyway, here's a different take on pad's solution. 无论如何,这是pad解决方案的另一种做法。
let split (delims: char[]) (str: string) =
str.Split(delims, StringSplitOptions.RemoveEmptyEntries)
let parse csvData =
let nl = Environment.NewLine.ToCharArray()
[ for x in split nl csvData -> split [|','|] x ]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.