简体   繁体   English

F#管道和LINQ

[英]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(...) )大致等同于使用ListSeqArray模块中的管道和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#的东西:

  • mutable 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)没有很好的支持。
  • You don't often need to use LINQ in F#, Array, List and Seq modules are more than adequate. 您通常不需要在F#中使用LINQ,而Array,List和Seq模块就足够了。
  • dot (.) syntax doesn't play nicely with pipe operators. 点(。)语法在管道运算符中无法很好地发挥作用。

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.

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