2009-07-12 2 views
6

Как создать и инициализировать массив в F # на основе заданного типа записи? Предположим, я хочу создать массив из 100 записей record1.Инициализация массива в F #

например.

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

let myArray = Array.init 100 ? 

Но, похоже, Array.init не позволяет этого, есть ли способ сделать это?

Edited добавить:

Конечно, я мог бы сделать что-то вроде этого:

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

ответ

11

Это должно делать то, что вам нужно. Надеюсь, поможет.

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

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

или с использованием Дженерики

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

Это не так эффективно, как ответ, используя 'Array.create', который должен создать только один объект записи вместо создания 100 отдельных объектов. Поскольку записи F # неизменяемы, нет недостатков, поскольку значение этого объекта никогда не изменится. (См. Мой комментарий к запросу 'Array.create' для получения более подробной информации.) – rmunn

11

Вы также можете использовать Array.create, который создает массив заданного размера, со всеми его элементами инициализированы до определенного значения:

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

ДАЙ посмотрите на этот список array operations.

+3

Уверены ли вы в этом? Для меня это создало массив из 100 элементов, указывающих на одну и ту же запись. Поэтому, если я говорю myArray. [5] .value1 <- 100, то myArray. [10] .value1 также вернет 100, потому что была только одна фактическая запись (я подозреваю). Когда я использовал Array.init 100 (fun x-> {value1 = "x"; value2 = "y"}), он работал, как ожидалось. – gjvdkamp

+1

@gjvdkamp - За исключением того, что по умолчанию записи F # неизменяемы, нет абсолютно никаких проблем с массивом из 100 элементов, указывающих на одну и ту же запись, если только вы не создали запись с изменяемыми полями. (Как правило, это плохая идея, потому что слишком много причин для включения в один комментарий). Если ваша запись неизменна, компилятор не позволит вам выполнить 'myArray. [5] .value1 <- 100'; вместо этого вы будете делать 'myArray. [5] .value1 = {myArray. [5] с value1 = 100} ', который создает * новый объект * и присваивает его этой позиции массива. Подробнее см. Https://fsharpforfunandprofit.com/posts/records/. – rmunn

2

Или вы можете создать последовательность, вместо того, чтобы создать массив, например:

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

Хорошая вещь об этой последовательности, вместо массива, является то, что он создает предметы, как вы нуждаетесь в них, а чем все сразу. И это просто, чтобы идти вперед и назад между последовательностями и массивами, если вам нужно.

Смежные вопросы