2016-03-31 8 views
10

Sto provando a convertire i miei for-loop nidificati in uno stile più funzionale.F # - Conversione di loop for nidificati in uno stile funzionale

Sono stato in giro con pipelining, sequenze e array, ma senza risultati.

Ecco quello che ho:

let allCarrierCodes = new List<string>()  
for result in getAllCarrierCodesResults do 
     for carrierCode in result do 
      allCarrierCodes.Add(carrierCode.ToString()) 
  • getAllCarrierCodesResults è un seguenti del tipo "obj lista"

Che cosa è un bel modo funzionale per ri-scrivere i cicli annidati?

Grazie.

+0

Oltre a riscrivere il ciclo nidificato, prendere in considerazione il passaggio dall'elenco "normale" ('System.Collections.Generic.List') a liste F #, che sono immutabili Vi darà accesso a tutte le chicche F # come il pattern matching. Con la risposta di Lee sotto, sarebbe 'lascia tutti i codici = getAllCarriesCodes |> Seq.concat |> stringa Seq.map |> List.ofSeq' –

risposta

10

È possibile utilizzare Seq.collect:

let allCodes = Seq.collect id getAllCarrierCodesResults 
       |> Seq.map string) 

o

let allCodes = Seq.collect (Seq.map string) getAllCarrierCodesResults 

si può poi convertire il conseguente seq<string> nella collezione di cemento che si desidera.

+0

Invece di scrivere' Seq.collect id', userei 'Seq.concat' . –

+0

Inoltre, è possibile utilizzare la nuova funzione in F # 4, dove [i costruttori possono essere utilizzati come funzioni di prima classe] (https://github.com/fsharp/FSharpLangDesign/blob/master/FSharp-4.0/ClassNamesAsFunctionsDesignAndSpec. md). Con questo, puoi scrivere 'let allCodes = getAllCarriesCodes |> Seq.concat |> Seq.map string |> List' Per l'uso di List, vedi il mio commento sopra. –

8

risposta di Lee è meglio di questo, ma volevo solo dire che si può assolutamente semplicemente mettere quei cicli annidati all'interno di una lista di comprensione, e voilà:

let allCarrierCodes = 
    [for result in getAllCarrierCodesResults do 
    for carrierCode in result do 
     yield carrierCode.ToString()] 

sembra tipo di imperativo-ish, ma è davvero funzionale.

Inoltre, è necessario utilizzare string carrierCode anziché carrierCode.ToString(). Ti protegge da NRE e sembra più funzionale per un ulteriore bonus :-)

+0

se consigli di non usare '.ToString()', perché lo usi nella tua risposta? – knocte

+0

Al fine di tenerlo il più vicino possibile al codice dell'OP. –