2009-07-12 41 views
6

Làm cách nào để tạo và khởi tạo một mảng trong F # dựa trên một loại bản ghi đã cho? Giả sử tôi muốn tạo một mảng gồm 100 bản ghi record1.Khởi tạo mảng trong F #

ví dụ:

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

let myArray = Array.init 100 ? 

Nhưng dường như Array.init không cho phép điều này, có cách nào để làm điều này không?

Edited thêm:

Dĩ nhiên tôi có thể làm một cái gì đó như thế này:

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

Trả lời

11

này nên làm những gì bạn cần. Hy vọng nó giúp.

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

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

hoặc sử dụng Generics

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

Điều này không hiệu quả như câu trả lời bằng cách sử dụng 'Array.create', mà chỉ phải tạo một đối tượng bản ghi thay vì tạo 100 đối tượng riêng biệt. Vì các bản ghi F # là không thay đổi, nên không có hạn chế nào vì giá trị của đối tượng đó sẽ không bao giờ thay đổi. (Xem bình luận của tôi về câu trả lời 'Array.create' để biết thêm chi tiết.) – rmunn

11

Bạn có thể sử dụng cũng Array.create, mà tạo ra một mảng có kích thước nhất định, với tất cả các yếu tố của nó khởi tạo một giá trị được xác định:

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

Hãy cho một cái nhìn vào danh sách này của array operations.

+3

Bạn có chắc chắn về điều này? Đối với tôi, điều này đã tạo ra một mảng gồm 100 mục tất cả trỏ đến cùng một bản ghi. Vì vậy, nếu tôi nói myArray. [5] .value1 <- 100, sau đó myArray. [10] .value1 cũng sẽ trả về 100 vì chỉ có một bản ghi thực sự (tôi nghi ngờ). Khi tôi sử dụng Array.init 100 (vui vẻ x-> {value1 = "x"; value2 = "y"}) nó hoạt động như mong đợi. – gjvdkamp

+1

@gjvdkamp - Ngoại trừ vì bản ghi F # không thay đổi theo mặc định, hoàn toàn không có vấn đề gì với một mảng gồm 100 mục trỏ đến cùng một bản ghi, trừ khi bạn đã tạo bản ghi với các trường có thể thay đổi. (Đó thường là một ý tưởng tồi, vì quá nhiều lý do để đi vào trong một bình luận duy nhất). Nếu bản ghi của bạn là bất biến, trình biên dịch sẽ không cho phép bạn thực hiện 'myArray. [5] .value1 <- 100'; thay vào đó, bạn sẽ làm 'myArray. [5] .value1 = {myArray. [5] với value1 = 100} ', tạo một đối tượng * mới * và gán nó cho vị trí mảng đó. Xem https://fsharpforfunandprofit.com/posts/records/ để biết thêm. – rmunn

2

Hoặc bạn có thể tạo ra một chuỗi, thay vì tạo một mảng, như thế này:

// 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|] 

Những điều tốt đẹp về trình tự, thay vì một mảng, là nó tạo ra mặt hàng như bạn cần họ, chứ không phải hơn tất cả cùng một lúc. Và thật đơn giản để chuyển qua lại giữa các chuỗi và các mảng nếu bạn cần.