arraysintro

Arrays Introduction | Vectors and Range Iterators | Sort and Sets | Matrices+ |
---|

- snippet.juliarepl
julia> pkgchk

**(****[****"**julia**"**=> v**"**1.0.2**"****]****)**

First-class treatment of arrays (of floats) are the feature that turns general-purpose languages into scientific languages. Julia is first-class!

- An array is an ordered mutable (i.e., read-write) collection of (same-type) elements.
- Arrays can be of any type (e.g., an array of Bools, such as
`Array{Bool,1}`

, which is a vector of Booleans). However, in practice, arrays are most often used for numerical containers, such as`Array{Float64,1}`

(a vector of Floats) or`Array{Int,2}`

(a matrix of integers). - Avoid arrays of
`Any`

to keep the discipline and type-checking of narrow types. Ideally, use only arrays of machine-native types. - Vectors and matrices are aliases for one- and two-dimensional arrays:

- snippet.juliarepl
julia> Array

**{**Int64**,**1**}**== Vector**{**Int64**}**true julia> Array**{**Int64**,**2**}**== Matrix**{**Int64**}**true julia> Vector Array**{**T**,**1**}**where T julia> Matrix Array**{**T**,**2**}**where T

- Dot functions operate scalar functions on arrays on an element-by-element basis:
`abs.([-2,3,-2])`

yields`[2,3,2]`

in-situ. - : JULIA PASSES EFFECTIVELY REFERENCES
- Functions never pass arrays, but references to arrays (“objects”). Thus, the function does not have copies of the vectors but aliases that refer to the same vector content.
- Assignments are function calls, so even assignments do not make copies:

- snippet.juliarepl
julia> a=

**[**1**,**2**]**;**(**b= a;**)**;**(**b**[**1**]**= –99; b**[**2**]**= –98;**)**; a 2-element Array**{**Int64**,**1**}**: –99 –98

- To make a copy of the contents
*in situ*, you can use the`.=`

operator:

- snippet.juliarepl
julia> a=

**[**1**,**2**]**; b=**[**0**,**0**]**;**(**b.= a**)**;**(**b**[**1**]**= –99; b**[**2**]**= –98;**)**; a 2-element Array**{**Int64**,**1**}**: 1 2

- You can also use
`copy()`

or`deepcopy()`

if you really need a copy and you do not want to clobber your original inadvertently. - : ACCIDENTAL TYPES AND OBJECTS DEFINITION MIXUPS

statement | result | explanation |
---|---|---|

`v= Vector{Float64}` | a type | desired? v is now an alias for a type. `x= v([NaN])` creates a float vector variable |

`v= Vector{Float64}(undef,10)` | an uninitialized variable | bad. v is a 10-element vector that holds garbage noise. |

`v= Vector{Float64}([10])` | an initialized variable | good. v is 1-element vector object. |

A common beginner's mistake is some variant of `v= Vector{Float64}; v + 0.0`

. A type and a value cannot be added.

Arrays are discussed in great detail in the next chapters.

- In R, execution speed demands expressing every operation in vectors. This is because the R user program is interpreted, but its underlying libraries are compiled. Expressing operations in vectors is usually
*not*helpful in Julia, because Julia compiles the user code, too. Thus, the fastest Julia operations are often based on plain old index-into-array manipulations—exactly the kind of operation that R suggests you to avoid.

Tuples may be so intuitive enough that you may not need to read the remainder of this chapter.

- A tuple is like a read-only array.
- Tuples use parentheses notation
`()`

instead of array bracket notation`[]`

. - Think of a tuple as a value that can only appear on the right side of an assignment. Think of an array as an object that can appear on the left or on the right side of an assignment.
`Any`

tuples are less harmful than`Any`

arrays, because tuples are read-only and create less havoc in the compiler optimizations.- Tuples can also be considered to be immutable structs (albeit nameless); or as the arguments to a function sans the function name.
- Tuples are well-suited to return many function return values. They can be typed like
`Tuple{Float64,Float64,Float64}`

or`NTuple{3,Float64}`

A tuple can pack elements, of any type, into a container. Tuples can hold specific values that are handed off as arguments to functions (or assignment to other data structures).

- snippet.juliarepl
julia>

**(****(**12**,****(****"**ab**"****,**true**)****,**13.0**)****)**## nested tuple --- outside-most parens are grouping**,**not tuple!**(**12**,****(****"**ab**"****,**true**)****,**13.0**)**julia> x=**(****(**12**,****(****"**ab**"****,**true**)****,**13.0**)****)**## variable x now holds**(**read-only**)**tuple**(**12**,****(****"**ab**"****,**true**)****,**13.0**)**julia> typeof**(**x**)**Tuple**{**Int64**,**Tuple**{**String**,**Bool**}****,**Float64**}**julia> dump**(**x**)**Tuple**{**Int64**,**Tuple**{**String**,**Bool**}****,**Float64**}**1: Int64 12 2: Tuple**{**String**,**Bool**}**1: String**"**ab**"**2: Bool true 3: Float64 13.0

Because parenthesis also serve for grouping, single-element tuples require special notation:

- snippet.juliarepl
julia> x=

**(**1**)**; typeof**(**x**)**## parens are groupings**,**so they group evaluations**,**and now you get a scalar**,**not a tuple! Int64 julia> x=**(****(**1**)****)**; typeof**(**x**)**## multiple parens are no better Int64 julia> x=**(**1**,****)**; typeof**(**x**)**## if you need a single-element tuple**,**the trailing comma is the special case notation Tuple**{**Int64**}**julia> typeof**(****(**1**,**2**,****)****)**== typeof**(****(**1**,**2**)****)**## here the trailing comma is optional true

parenthesis notation is also used to group statements.

- snippet.juliarepl
julia>

**(****'**a**'****,****'**b**'****,**3**)****[**1**]****'**a**'**: ASCII/Unicode U+0061**(**category Ll: Letter**,**lowercase**)**julia> x=**(****'**a**'****,****'**b**'****,**3**)**; x**[****[**3**,**1**,**2**,**2**]****]****(**3**,****'**a**'****,****'**b**'****,****'**b**'****)**julia> x**[**2**]****'**b**'**: ASCII/Unicode U+0062**(**category Ll: Letter**,**lowercase**)**julia> x**[**2**]**=**'**c**'**## tuples are readonly! ERROR: MethodError: no method matching setindex!**(**::Tuple**{**Char**,**Char**,**Int64**}****,**::Char**,**::Int64**)**Stacktrace:

- snippet.juliarepl
julia> t1=

**(**:a**,**:b**)**; t2=**(**:c**,**:d**)**; ## define two tuples julia>**(**t1**,**t2**)**## creates a nested tuple**(****(**:a**,**:b**)****,****(**:c**,**:d**)****)**julia> vcat**(**t1**,**t2**)**## an *array* of tuples 2-element Array**{**Tuple**{**Symbol**,**Symbol**}****,**1**}**:**(**:a**,**:b**)****(**:c**,**:d**)**julia>**(**t1...**,**t2...**)**## a merged single tuple**(**:a**,**:b**,**:c**,**:d**)**

The contents of an tuple can be unpacked for passing as the arguments of a function, too. This can work even using the `...`

operator. For example:

- snippet.juliarepl
julia> f

**(**x**,**y**)**= x + y f**(**generic function with 1 method**)**julia> t=**(**1**,**2**)****(**1**,**2**)**julia> f**(**t...**)**3

You may never need the information in this section.

To convert x from a tuple into an array

- snippet.juliarepl
julia> tup3=

**(****(**12**,**3**)****,****[**1.0**,**2.0**]****,****[****"**A**"****,****'**n**'****,**13**]****)****(****(**12**,**3**)****,****[**1.0**,**2.0**]****,**Any**[****"**A**"****,****'**n**'****,**13**]****)**julia> typeof**(**tup3**)**Tuple**{**Tuple**{**Int64**,**Int64**}****,**Array**{**Float64**,**1**}****,**Array**{**Any**,**1**}****}**julia>**[**i for i in tup3**]**3-element Array**{**Any**,**1**}**:**(**12**,**3**)****[**1.0**,**2.0**]**Any**[****"**A**"****,****'**n**'****,**13**]**

Julia could not know whether you meant

- snippet.juliarepl
julia>

**(****(**1**,**2**)****,****(**3**,**4**)****,****(**5**,**6**)****)****(****(**1**,**2**)****,****(**3**,**4**)****,****(**5**,**6**)****)**

to be a matrix or a 3-tuple of 2-tuples, so if you want to interpret it and convert it to a 3×2 matrix, then use the `reinterpret()` function.

- snippet.juliarepl
julia> x=

**[**1**,**2**,**3**,****"**ab**"****,**true**]**5-element Array**{**Any**,**1**}**: 1 2 3**"**ab**"**true julia> tuple**(**x**)**## tuple with array inside**,**not a conversion**(**Any**[**1**,**2**,**3**,****"**ab**"****,**true**]****,****)**julia> tuple**(**x...**)**## tuple of elements from array**(**1**,**2**,**3**,****"**ab**"****,**true**)**julia> Tuple**(**x**)****(**1**,**2**,**3**,****"**ab**"****,**true**)**

The trailing comma on the tuple output helps to distinguish `(1+2,)`

from (1+2)

A tuple is *not* an array. A variable can hold either a tuple or an array.

- snippet.juliarepl
julia>

**(****(**12**,****(****"**ab**"****,**true**)****,**13.0**)****,****(**12**,**13.0**)****)****(****(**12**,****(****"**ab**"****,**true**)****,**13.0**)****,****(**12**,**13.0**)****)**julia>**[****(**12**,****(****"**ab**"****,**true**)****,**13.0**)****,****(**12**,**13.0**)****]**2-element Array**{**Tuple**{**Int64**,**Any**,**Vararg**{**Float64**,**N**}**where N**}****,**1**}**:**(**12**,****(****"**ab**"****,**true**)****,**13.0**)****(**12**,**13.0**)**

For a mixed version

- snippet.juliarepl
julia> x=

**(****(**12**,**3**)****,****[**1.0**,**2.0**]****,****[****"**A**"****,****'**n**'****,**13**]****)****(****(**12**,**3**)****,****[**1.0**,**2.0**]****,**Any**[****"**A**"****,****'**n**'****,**13**]****)**julia> typeof**(**x**)**Tuple**{**Tuple**{**Int64**,**Int64**}****,**Array**{**Float64**,**1**}****,**Array**{**Any**,**1**}****}**

You can now change `x[2][2]`

(because it sits in an array), but not `x[1][2]`

(because it sits in a tuple).

- snippet.juliarepl
julia> x=

**(****(**12**,**3**)****,****[**1.0**,**2.0**]****,****[****"**A**"****,****'**n**'****,**13**,****(**3**,**4**)****,****[**5**,**6**]****]****,****)****(****(**12**,**3**)****,****[**1.0**,**2.0**]****,**Any**[****"**A**"****,****'**n**'****,**13**,****(**3**,**4**)****,****[**5**,**6**]****]****)**

How to descend into mixed tuple/array structure, and make all tuple or all array out of it.

- snippet.juliafix
[download only julia statements] julia> tupelize( x ) ((12, 3), (1.0, 2.0), ("A", 'n', 13, (3,4), [5,6])) julia> arraylize( x ) [[12, 3], [1.0, 2.0], Any["A", 'n', 13, [3,4], [5,6]]]

- Unfortunately, it is not possible to turn on a compiler warning whenever an uninitialized variable is used before assignment.
- There is also a more
`AbstractArray`

type. It is usually used as function arguments when the function should work not only on arrays but also on similar types (data structures like`Diagonal`

). This chapter ignores this.`AbstractArray{T,N}`

can also be useful, e.g., for sorting, but is too complex for this tutorial and thus ignored. - It is a pity that julia does not force type declarations for objects, but silently obliges to create them. This makes it easy to accidentally declare arrays with too broad a type, especially Any array types—which hoses both julia's type-checking and efficiency.
- NamedTuples used to allow
`x= @NT( a=1, b=2 )`

, but are not working in Julia 1.0 in Sep 2018.

- Julia DataArrays which allow for Missing data

arraysintro.txt · Last modified: 2018/11/22 20:47 (external edit)