2009-07-12 5 views
6

Come si crea e inizializza una matrice in F # in base a un determinato tipo di record? Supponiamo di voler creare una serie di 100 record1.Inizializzazione di array in F #

ad es.

 
type record1 = { 
    value1:string; 
    value2:string 
} 

let myArray = Array.init 100 ? 

Ma sembra che l'array.init non lo consenta, c'è un modo per farlo?

A cura di aggiungere:

Naturalmente avrei potuto fare qualcosa di simile:

 
let myArray = [|for i in 0..99 -> { value1="x"; value2="y" }|] 

risposta

11

Questo dovrebbe fare quello che ti serve. Spero che sia d'aiuto.

type record1 = { 
    value1:string; 
    value2:string 
} 

let myArray = Array.init 100 (fun x -> {value1 = "x"; value2 = "y"}) 

o utilizzando Generics

let myArray = Array.init<record1> 100 (fun x -> {value1 = "x"; value2 = "y"}) 
+1

Questo non è efficiente come la risposta utilizzando 'Array.create', che deve solo creare un singolo oggetto record invece di creare 100 oggetti separati. Poiché i record F # sono immutabili, non ci sono inconvenienti poiché il valore dell'oggetto non cambierà mai. (Vedi il mio commento sulla risposta 'Array.create' per maggiori dettagli.) – rmunn

11

È possibile utilizzare anche Array.create, che crea una matrice di una data dimensione, con tutti i suoi elementi inizializzati ad un valore definito:

let myArray = Array.create 100 {value1="x"; value2="y"} 

Dare un'occhiata a questo elenco di array operations.

+3

Sei sicuro di questo? Per me questo ha creato una serie di 100 elementi che puntavano tutti allo stesso record. Quindi, se dico myArray. [5] .value1 <- 100, poi myArray. [10] .value1 restituirebbe anche 100 perché c'era solo un record reale (ho il sospetto). Quando ho usato Array.init 100 (fun x-> {value1 = "x"; value2 = "y"}) ha funzionato come previsto. – gjvdkamp

+1

@gjvdkamp - Tranne che poiché i record F # sono immutabili per impostazione predefinita, non c'è assolutamente alcun problema con una serie di 100 elementi che puntano tutti allo stesso record, a meno che non si sia creato un record con campi mutabili. (Che di solito è una cattiva idea, per troppi motivi per entrare in un singolo commento). Se il tuo record è immutabile, il compilatore non ti permetterà di fare 'myArray. [5] .value1 <- 100'; invece, dovresti fare 'myArray. [5] .value1 = {myArray. [5] con value1 = 100} ', che crea un * nuovo oggetto * e lo assegna a quella posizione dell'array. Vedi https://fsharpforfunandprofit.com/posts/records/ per ulteriori informazioni. – rmunn

2

oppure è possibile creare una sequenza, invece di creare un array, in questo modo:

// nItems, given n and an item, returns a sequence of item repeated n times 
let rec nItems n item = 
    seq { 
    match n with 
    | n when n > 0 -> yield item; yield! nItems (n - 1) item 
    | _ ->() 
    } 

type Fnord = 
{ foo: int } 

printfn "%A" (nItems 99999999 {foo = 3}) 
// seq [{foo = 3;}; {foo = 3;}; {foo = 3;}; {foo = 3;}; ...] 

printfn "%A" (nItems 3 3 |> Seq.toArray) 
[|3; 3; 3|] 

La cosa bella la sequenza, invece di un array, è che crea oggetti quando ne hai bisogno, piuttosto di tutti in una volta. Ed è semplice andare avanti e indietro tra sequenze e array se necessario.