Multidimensional Understanding Array in Julia

I work with Julia and cannot make multidimensional array decisions work. I use the 0.20-pre nightly build for OSX; perhaps this could be a build error. However, I suspect this is a user error.

Suppose I want to complete something like:

5x2 Array 1 6 2 7 3 8 4 9 5 10 

And I do not want to just call reshape . From what I can say, a multidimensional array should be generated something like this: [(x, y) for x in 1:5, y in 6:10] . But this spawns an array of 5x5 tuples:

 julia> [(x, y) for x in 1:5, y in 6:10] 5x5 Array{(Int64,Int64),2}: (1,6) (1,7) (1,8) (1,9) (1,10) (2,6) (2,7) (2,8) (2,9) (2,10) (3,6) (3,7) (3,8) (3,9) (3,10) (4,6) (4,7) (4,8) (4,9) (4,10) (5,6) (5,7) (5,8) (5,9) (5,10) 

Or maybe I want to generate a set of values ​​and a logical code for each:

 5x2 Array 1 false 2 false 3 false 4 false 5 false 

Again, I can only create an array of tuples with {(x, y) for x in 1:5, y=false} . If I remove the parsers around x, y , I get ERROR: syntax: missing separator in array expression . If I wrap x, y in something, I always get this type of output - Array , Array{Any} or Tuple .

My guess: there is something I just can't get here. Anyone who wants to help me understand that?

+6
source share
7 answers

I do not think that understanding is suitable for what you are trying to do. The reason can be found in the "Defining Array" section of the Julia Guide :

 A = [ F(x,y,...) for x=rx, y=ry, ... ] 

The meaning of this form is that F (x, y, ...) is evaluated with variables x, y, etc., taking each value in their list of values. Values ​​can be specified as any iterable object, but usually it is ranges, such as 1: n or 2: (n-1), or explicit arrays of values, such as [1.2, 3.4, 5.7]. The result is a dense array of Nd with dimensions that are the concatenation of the sizes of the ranges of the variables rx, ry, etc., and each estimate F (x, y, ...) returns a scalar.

The danger here is that if you set one of the variables to> 1-dimensional array, it seems to be flattened first; therefore, the statement that "the result is ... an array with dimensions that are the concatenation of the sizes of the ranges of the variables rx, ry, etc." is not very accurate, because if rx is 2x2 and ry is 3, then you are not will get the result 2x2x3, but rather 4x3. But the result you get should make sense in light of the above: you return a tuple, so that what happens in the Array cell. There is no automatic extension of the returned tuple to an array string.

If you want to get a 5x2 array from the contents, you need to make sure that x has a length of 5 and y has a length of 2. Then each cell will contain the result of the function being evaluated with each possible pairing of elements from x and y as arguments. The fact is that the values ​​in the cells of your array of examples do not really require evaluating a function of two arguments. Rather, what you're trying to do is simply insert two predefined columns into a two-dimensional array. To do this, use hcat or a literal:

  • hcat(1:5, 6:10)
  • [ 1:5 5:10 ]
  • hcat(1:5, falses(5))
  • [ 1:5 falses(5) ]

If you want to create a 2D array in which column 2 contains the result of the function evaluated in column 1, you can do this with understanding as follows:

 f(x) = x + 5 [ y ? f(x) : x for x=1:5, y=(false,true) ] 

But this is a bit confusing, and seems to me more intuitive to just do

 x = 1:5 hcat( x, map(f,x) ) 
+6
source

I think you are just reading the list incorrectly.

 julia> [x+5y for x in 1:5, y in 0:1] 5x2 Array{Int64,2}: 1 6 2 7 3 8 4 9 5 10 

When you use them in multiple dimensions, you get two variables and need a function for cell values ​​based on coordinates

For your second question, I think you should reconsider your requirements. Julia uses typed arrays to improve performance and store different types in different columns. To get an untyped array, you can use {} instead of [], but I think the best solution would be to have an array of tuples (Int, Bool) or even better to use only two arrays (one for int and one for bool).

 julia> [(i,false) for i in 1:5] 5-element Array{(Int64,Bool),1}: (1,false) (2,false) (3,false) (4,false) (5,false) 
+8
source

Your intuition was to write [(x, y) for x in 1:5, y in 6:10] , but you need to wrap the ranges in zip , for example:

 [i for i in zip(1:5, 6:10)] 

Which gives you something very close to what you need, namely:

 5-element Array{(Int64,Int64),1}: (1,6) (2,7) (3,8) (4,9) (5,10) 

To get exactly what you are looking for, you will need:

 hcat([[i...] for i in zip(1:5, 6:10)]...)' 

This gives you:

 5x2 Array{Int64,2}: 1 6 2 7 3 8 4 9 5 10 
+1
source

This is another (albeit confusing) way:

 x1 = 1 x2 = 5 y1 = 6 y2 = 10 x = [x for x in x1:x2, y in y1:y2] y = [y for x in x1:x2, y in y1:y2] xy = cat(2,x[:],y[:]) 
0
source

As @ivarne noted

 [{x,false} for x in 1:5] 

will work and give you something mutable

0
source

I kind of gave @fawr's answer for data type efficiency, while preserving the variability, but it quickly gives you what you asked (working off Sean's answer):

 hcat(1:5,6:10) hcat({i for i=1:5},falses(5)) 

The concept of a cell in the second part makes the data type be Any, not IntXX

This also works:

 hcat(1:5,{i for i in falses(5)}) 

I did not find another way to explicitly convert the array to input Any, other than understanding.

0
source

I found a way to create numeric multidimensional arrays using vcat and the splat operator:

 R = [ [xy] for x in 1:3, y in 4:6 ] # make the list of rows A = vcat(R...) # make n-dim. array from the row list 

Then R will be 3x3 Array{Array{Int64,2},2} , and A is 9x2 Array{Int64,2} , as you want.

For the second case (a set of values ​​and a Boolean code for each), you can do something like

 R = [[xy > 5] for x in 1:3, y in 4:6] # condition is y > 5 A = vcat(R...) 

where A will be 9x2 Array{Int64,2} , where true / false denoted by 9x2 Array{Int64,2} .

I tested those that were in Julia 0.4.7.

0
source

Source: https://habr.com/ru/post/955875/


All Articles