onlyvix.blogspot.com
onlyvix.blogspot.com

Reputation: 347

F# jagged array assignment

I am getting strange behavior - when I assign a single value to a jagged array, it changes values of the entire column.

let testArray = Array.create 5 (Array.create 5 nan)
testArray.[3].[3] <- 1.0

The code above, instead of changing the value of a single cell, changes the value of the entire column.

val it : float [] [] =
  [|[|nan; nan; nan; 1.0; nan|]; [|nan; nan; nan; 1.0; nan|];
  [|nan; nan; nan; 1.0; nan|]; [|nan; nan; nan; 1.0; nan|];
  [|nan; nan; nan; 1.0; nan|]|]

Upvotes: 2

Views: 715

Answers (1)

Fyodor Soikin
Fyodor Soikin

Reputation: 80754

This happens because you're not creating a 2-dimensional array (as I assume you expect), but rather you're creating exactly two arrays: one array with 5 nans in it, and another array with 5 references to the first array in it. Just to illustrate the matter, the following code is completely equivalent to yours:

let firstArray = Array.create 5 nan
let testArray = Array.create 5 firstArray
testArray.[3].[3] <- 1.0

So that the line testArray.[3].[3] <- 1.0 actually changes only one element - the fourth one in firstArray, but if you then try to print out testArray, that same element shows up multiple times, because there are multiple references to firstArray.

If you wanted to create an array with five different arrays in it, you need to use Array.init, which instead of the element takes a "create next element" function:

let testArray = Array.init 5 (fun _ -> Array.create 5 nan)

Alternatively, you can use list comprehension to create the array:

let testArray = [|for i in 1..5 -> Array.create 5 nan|]

Both will give you the same result, though the first one will have slightly better performance.

If you really need to work with two-dimensional arrays (rather than arrays of arrays), you might want to look at Array2D instead:

let testArray = Array2D.create 5 5 nan
testArray.[3,3] <- 1.0

Upvotes: 13

Related Questions