2009-12-31 10 views
15

Con un array let foo = [|1;2;3;4|] È possibile utilizzare uno dei seguenti elementi per restituire una porzione da un array.Taglia come funzionalità da un elenco in F #

foo.[..2] 
foo.[1..2] 
foo.[2..] 

Come posso fare la stessa cosa per la Lista let foo2 = [1;2;3;4]? Quando provo la stessa sintassi dell'array ottengo error FS00039: The field, constructor or member 'GetSlice' is not defined.

Qual è il metodo preferito per ottenere una sottosezione di un elenco e perché non sono stati creati per supportare GetSlice?

risposta

36

Qual è il metodo preferito di ottenere una sottosezione di una lista e il motivo per cui non sono costruito per sostenere GetSlice?

Facciamo l'ultima domanda prima e la prima domanda ultima:

Perché liste non supportano GetSlice

liste sono implementate come liste collegate, in modo da non abbiamo efficiente indicizzati accesso a loro. Comparativamente, foo.[|m..n|] richiede il tempo O(n-m) per gli array, una sintassi equivalente richiede tempo O(n) negli elenchi. Questo è un grosso problema, perché ci impedisce di usare la sintassi per affettare in modo efficiente nella maggior parte dei casi in cui sarebbe utile.

Ad esempio, si può tagliare un array in pezzi di dimensioni uguali in tempo lineare:

let foo = [|1 .. 100|] 
let size = 4 
let fuz = [|for a in 0 .. size .. 100 do yield foo.[a..a+size] |] 

Ma se usavamo un elenco invece? Ogni chiamata a foo.[a..a+size] richiederebbe più tempo, più a lungo e più a lungo, l'intera operazione è O(n^2), rendendolo piuttosto inadatto per il lavoro.

La maggior parte delle volte, tagliare un elenco è l'approccio sbagliato. Normalmente usiamo la corrispondenza del modello per attraversare e manipolare le liste.

Metodo preferito per tagliare un elenco?

Ove possibile, utilizzare la corrispondenza del modello se è possibile. In caso contrario, si può ripiegare su Seq.skip e Seq.take di tagliare elenchi e sequenze per voi:

> [1 .. 10] |> Seq.skip 3 |> Seq.take 5 |> Seq.toList;; 
val it : int list = [4; 5; 6; 7; 8] 
8

F # 4.0 consentirà affettare sintassi per le liste (link).

logica è here:.

Il tipo F # elenco supporta già un operatore di indice, xs [3]. Ciò avviene nonostante il fatto che le liste siano elenchi concatenati in F # - gli elenchi sono così comunemente usati in F # che in F # 2.0 è stato deciso di supportarlo.

Poiché una sintassi dell'indice è supportata, ha senso supportare anche la sintassi dell'affettatura F #, ad es. xs. [3..5]. È molto strano dover passare a un tipo di matrice per utilizzare l'affettatura, ma non è necessario effettuare tale conversione per l'indicizzazione.

Ancora, Juliet risponde, dicendo che, il più delle volte tagliare una lista è l'approccio sbagliato, è ancora vero. Quindi sii saggio quando usi questa funzione.

Problemi correlati