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]