In Haskell, esiste una funzione "take n list" che restituisce i primi n elementi da un elenco. Ad esempio "sum (take 3 xs)" riassume i primi tre elementi nell'elenco xs. F # ha un equivalente? Mi aspettavo che fosse una delle funzioni di elenco, ma non riesco a individuare nulla che sembra corrispondere.F # ha un equivalente di Take di Haskell?
risposta
Sì, si chiama Seq.take
. L'utilizzo sembra essere identico a quello di Haskell: Seq.take
count source.
Per utilizzarlo su un elenco, utilizzare prima
(Aggiornamento: A quanto pare dai commenti, questo non è necessario.)List.toSeq
.
Per chiarire un paio di cose, la differenza tra Seq.take
e Seq.truncate
(come sottolineato da @ sepp2k) è che la seconda vi darà una sequenza di che restituisce al massimo il numero di elementi specificati (ma se la lunghezza della sequenza è inferiore, fornirà meno elementi).
La sequenza generata Seq.take
funzione un'eccezione se si tenta di accedere a un elemento al di là della lunghezza della lista originale (Si noti che la funzione Seq.take
non genera immediatamente l'eccezione, perché il risultato è pigramente generato sequenza).
Inoltre, non è necessario convertire esplicitamente la lista in una sequenza. Sotto la copertina, list<'a>
è una classe .NET che eredita dal tipo seq<'a>
, che è un'interfaccia. Il tipo seq<'a>
è in realtà solo un alias di tipo per IEnumerable<'a>
, quindi è implementato da tutte le altre raccolte (inclusi array, elenchi modificabili, ecc.). Il seguente codice funziona bene:
let list = [ 1 .. 10 ]
let res = list |> Seq.take 5
Tuttavia, se si vuole ottenere un risultato di tipo list<int>
avrete bisogno di convertire la sequenza di nuovo a una lista (perché l'elenco è di tipo più specifico di una sequenza):
let resList = res |> List.ofSeq
io non sono sicuro perché F # librerie non forniscono List.take
o List.truncate
. Immagino che l'obiettivo fosse evitare di reimplementare l'intero set di funzioni per tutti i tipi di collezioni, quindi quelle in cui l'implementazione per le sequenze è abbastanza buona quando si lavora con un tipo di raccolta più specifico sono disponibili solo nel modulo Seq
(ma questa è solo la mia ipotesi ...)
Bel chiarimento. – McMuttons
@McMuttons: Grazie! Non ero sicuro di doverlo postare o meno, perché la maggior parte delle cose erano già menzionate nei commenti .. Quindi, sono contento che sia usato! –
Seq.take funziona, come altri hanno già detto, ma tutte le operazioni Seq su una lista hanno un costo. Nel caso di Seq.take, non è sorprendente, poiché l'elenco deve essere copiato.
È più interessante notare che, ad esempio, Seq.concat in un elenco richiede molto più tempo di List.concat.
Suppongo che ciò implichi che non si accede alla lista come seq quando si chiama una funzione Seq.xxx, ma che l'elenco viene copiato/convertito in Seq anche dietro le quinte.
edit: La ragione per cui ho tratto la conclusione di cui sopra, è stato questo panchina con F # interattivo:
#time "on";;
let lists = [for i in 0..5000000 -> [i..i+1]];;
Seq.length (Seq.concat lists);;
List.length (List.concat lists);;
Sulla mia macchina, la versione List.length
dura circa 1,9 secondi, mentre la versione Seq.length
dura circa 3.8 secondi (il tempo più breve di alcuni test ripetuti delle sole linee di lunghezza, esclusa la riga di generazione dell'elenco).
Non penso che sia corretto. 'lista <'t>' implementa l'interfaccia 'seq <'t>' in modo che non sia necessaria alcuna conversione, né vi è motivo di aspettarsi che una copia venga eseguita. Inoltre, 'Seq.take' funziona pigramente, mentre' List.take' non può, quindi su una lunga lista, le operazioni di sequenza saranno quasi certamente più veloci se è necessario solo il fronte della sequenza risultante. Tuttavia, potrebbe essere vero che l'implementazione di una funzione 'List.take' tramite la corrispondenza dei pattern avrebbe prestazioni migliori rispetto all'implementazione' Seq.take' che enumera l'elenco se si desidera accedere con impazienza a tutti gli elementi della lista risultante. – kvb
La mia conclusione sulle conversioni in corso è probabilmente sbagliata, ma qualcosa sta succedendo e ci vuole più tempo. Ho modificato il mio post e aggiunto alcuni tempi. – Batibix
- 1. Fa Elm ha un equivalente di Haskell As-modello
- 2. Elm ha un equivalente di "Read" di Haskell
- 3. Rust ha un equivalente idiomatico di typedef F #?
- 4. fa Idris ha un equivalente di Agda ↔
- 5. Haskell equivalente di Scala raccoglie
- 6. equivalente di rubino ...? in Haskell
- 7. Haskell equivalente di C __LINE__
- 8. "Curl -F" Java equivalente
- 9. Angular2 ha un equivalente di $ documento
- 10. Java ha un equivalente di riferimento const?
- 11. Scala ha un operatore simile a `$` di Haskell?
- 12. "Show derivante" di Haskell in F #?
- 13. F # versione di corrispondenza del modello haskell
- 14. Equivalente alla notazione Haskell o alle espressioni di calcolo F # in Scala?
- 15. Equivalente tessuto in Haskell?
- 16. Come implementare un equivalente pitone di coda -F?
- 17. Esiste un F # equivalente alla Promessa di Scala?
- 18. Esiste un equivalente di tail -f su Windows?
- 19. Linq: l'opposto di Take?
- 20. In Scala, c'è un equivalente di Haskell "fromListWith" per Map?
- 21. Haskell ha foldlM '?
- 22. Equivalente di urllib Python in Haskell
- 23. Java ha un equivalente StringStream?
- 24. VBScript ha un equivalente DateTime.TryParse?
- 25. NotifyIcon ha un equivalente MouseDown?
- 26. F # List.map equivalente in C#?
- 27. Haskell ha funzioni/tuple variadiche?
- 28. Haskell ha variabili?
- 29. java equivalente a printf ("% *. * F")
- 30. Equivalente di eval python in Haskell
Questo sembra essere esattamente quello che sto cercando. Testare ora. :) – McMuttons
In realtà, il take di haskell agisce come Seq.truncate, non Seq.take. – sepp2k
Poiché l'elenco eredita da IEnumerable, non è necessario convertirlo prima in una sequenza da quello che posso vedere. Usare Seq.take in una lista ha funzionato bene. – McMuttons