## Array Class

Arrays are sequences of heterogeneous elements, are represented as a comma separate list between square brackets; an integer index, between square brackets is used to refer to single elements; We can have arrays of arrays, simulating multi-dimensional structures.

The class mixes in the Enumerable module , with a lot of iterators.

In the following figure the hierarchy of the Array and Hash classes; some class methods are listed in the square box. Arrays can be created in the following ways:

```a=Array.new          : an empty array

a=Array.new(3)       : to make an array of 3 elements containing "nil"

a=Array.new(3,"a")   : to make an array of 3 elements containing the object: "a"

a=[12,"asd",3.5E3,1,2,3]   : another way to make an array
```

To make an array from words in a string:

```a= %w{ a b c d \n  }  => ["a", "b", "c", "d", "\\n"]

a= %W{ a b c d \\n  } => ["a", "b", "c", "d", "\n"]
```

if "%w" is used, backslash symbols are not interpreted, as in single-quoted strings. If "%W" is used, backslash are interpreted as in double-quoted strings

The "split" function can obtain an array from a string, the "join" function obtains a string from an array.

The '*' operator can act as a join for arrays, if the second operator is a string:

```"1-2-3".split("-") => ["1", "2", "3"]
[1,2,3].join("-")  => "1-2-3"

[1,2]*"a"  => "1a2"
```

Some operators and functions for arrays are listed in the following table:

 + concatenates: "a"+"b" => "ab" - difference: [1,1,2,3] - [1,2,4] =>  * array repetition: *2 => [1, 1] concat concatenates: .concat() => [1, 1] & common elements: [1,2] & [2,3] =>  | add without duplicates: [2,2,3] | [1,2,4] => [ 2, 3, 1, 4] << append elements: <<2 => [1, 2] include?(value) true if the value is included: [1,2].include?(1) => true empty? true if empty length number of elements count counts elements: [1,2,1].count => 3 ; [1,2,1].count(1) => 2 compact ; compact! removes nil elements uniq ; uniq! remove duplicates: [1,2,2].uniq => [1, 2] delete(value) fetches and deletes an item, given its value delete_at(n) fetches and deletes an item, given the position insert(index,value) insert at the given position: [1,2].insert(1,5) => [1,5,2] fill(value) change each element to the given value first(n) first elements: [1,2,3].first(2) => [1, 2] last(n) last elements: [1,2,3].last(2) => [2, 3] max maximum element: [1,3,2].max => 3 min minimum element: [1,3,2].min => 1 flatten makes uni-dimensional: [[1,2],[3,4]].flatten => [1,2,3,4] transpose in 2-dimensional transposes row and columns join(separator) joins elements into a string: [1,2].join("-") => "1-2" combination(n).to_a array with the all combinations of n elements of the array permutations(n).to_a all permutations of n elements repeated_combination(n) all combinations with repetitions repeated_permutations all permutations with repetitions replace(newarray) replaces with an other array reverse ; reverse! reverses the order o f elements rotate(n) ; rotate!(n) circular shift: [1,2,3].rotate(1) => [2, 3, 1] sample(n) extracts n random elements unshift(1) add a first element .unshift(2) => [2, 1] shift(n) extracts and deletes first n elements push(value) add an element at the end: .push(2) => [1, 2] pop(n) extract and deletes elements from the end shuffle ; shuffle! random reordering sort ; sort! sorts elements:[2,1].sort=>[1, 2]; ["b","a"].sort=>["a","b"] to_s a string representing the array

flatten has an optional argument: the number of dimension to eliminate:

```a=[1,2,[13,14],[15,[26,[37,38]]]]

a.flatten(1) => [1, 2, 13, 14, 15, [26, [37, 38]]]

a.flatten(2) => [1, 2, 13, 14, 15, 26, [37, 38]]

a.flatten(3) => [1, 2, 13, 14, 15, 26, 37, 38]

a.flatten    => [1, 2, 13, 14, 15, 26, 37, 38]
```

to_a, a member Enumerable, creates an array from a sequence.

zip combines arrays element by element, producing an array of arrays:

```(1..3).zip [ "a","b","c"]             => [[1, "a"], [2, "b"], [3, "c"]]

[1,2,3].zip([10,20,30],["a","b","c"]) => [[1, 10, "a"], [2, 20, "b"], [3, 30, "c"]]

(1..3).zip                            => [, , ]
```

### The Subscript Operator: []

"[]" returns single bits for numbers, characters for strings, elements of arrays; inside the square brackets we can have numbers, ranges or also regular expressions:

```a=[1,2,3,4] ;

a => 1                # index begins from zero
a[-1]=> 4                # negative indexes from the end
a[a.size-1]              # last element

a[0..2]   => [1, 2, 3]   # extracts using a range (last element included)
a[0...2]  => [1, 2]      # extracts using a range (last element NOT included)
a[-4..-2] => [1, 2]

a[0,2]  => [1, 2]        # a sub-array (2 elements from 0)
a[1,2]  => [2, 3]        # 2 elements , from 1
a[-3,2] => [2, 3]        # 2 elements , from -3 ( a[-3]=> 2 )
a[-4,2]    => [1, 2]     # from element -4 (the first) takes 2 elements

a[/regular expr/]        # regular expressions can be used too

a.first(2) => [1, 2]     # first elements
a.last(2)  => [3, 4]     # last elements

a=[1,2,3,4] ; a=['a','b']=> ["a", "b", 2, 3, 4] # reassigns a range of elements
```

An element is changed or added with the "[]=" operator; nil elements are created to void the gaps:

```a= ; a=3    => [0, nil, nil, 3]

a=[1,2,3,4]
a[0,2]=0      => [0, 3, 4]     # starting from position 0, sets 2 elements

a=[1,2,3,4]
a[0,2]=5,6    => [5, 6, 3, 4]  # multiple assignments are possible
a[0,2]=[5,6]  => [5, 6, 3, 4]

a=[1,2,3,4]
a[-1]=9       => [1, 2, 3, 9]  # negative indexes counts from the end
```

## Hash Class

Hashes, also named maps, or associative arrays, or dictionaries, are sequences of objects, not retrieved by an integer index, but by a key, which can be any object. Hashes are written as key/value pairs, separated by an arrow, in curly braces, Es.: (1=>"a",2=>"b"}

Hashes mixes in the Enumerable module, with a lot of useful iterators.

The elements are in the order in which they have been inserted in the hash; the last element being the last inserted.

The attempt to access to a non-existing elements returns nil or a default value which can be set at the hash creation or with the default= method.

For hashes the operator "[]" returns values, based on keys; symbols can also be used as keys, for a faster access::

```a={"one" => 1, "two" =>2 ,3 => "a"}

a["one"] => 1
a     => "a"

h["a"]=723                # adds, or replaces, en element

h={ :one => 1, :two =>2 } # symbols can be used as keys

h={one: 1 , two: 2 }      # alternate syntax, possible  when keys are symbols
```

Operators and methods for hashes are listed in the following table:

 a=Hash.new makes an empty hash a={} makes an empty hash a=Hash.new("default") makes an empty hash defining the default value default returns the default value default= sets the default value delete deletes an element by key Es.: h.delete("one") fetch fetches element by key: h.fetch(key) has_key? ;include? : key? True if a key is present: h.has_key?(k) has_value? true if a value is present: h.has_value?(val) merge ; merge! merges hashes, duplicate keys are overwritten: h.merge(h2) sort sorted array of pairs: [[key1,value],[key2,value]..] flatten(n) array with keys and values, with n dimensions flattened invert keys become values and values keys flatten(n) array with keys and values, with n dimensions flattened empty? true if the hash is empty: {}.empty? => true length ; size number of elements values array with values h.keys array with keys h[key] a value, given the key (the default value if key not found) h[key]=value adds, or changes, the value for a given key key(value) a key, given a value clear voids an hash sort an ordered array of [key,value] ,ordered by keys shift extracts and remove the first [key,value] pair to_a array of [key,value] pairs to_s a string representing the hash

## Range Class

Range objects represent an interval in a sequence, are mainly used in loops and case statements, but also as indexes of arrays and strings. Ranges mixes in the module Enumerable, with a lot of iterators.

Ranges are written as two numbers or characters separated by two or three dots. When three dots are used the last object is not included, when two are used the last element is included.

Not only numbers or characters can be used to make a Range object, but every object which can be treated as a sequence, responding to the comparison method: "<=>" and the "succ" method (which gives the next item of the sequence).

The Range method can be used to built ranges:

```a=Range.new(1,3)
1..3             => 1,2,3   # last element is INCLUDED

a=Range.new(1,3,true)
1...3            => 1,2   ; range with last element NOT INCLUDED

(1...3).exclude_end? : true

-3..-1         => -3,-2,-1

'a'..'c'     # range of characters

1.2..3.5    # range of float (but you can't iterate on these)

a=[0,1,2,3,4]
a[1..3]        => [1, 2, 3]
a[1...3]       => [1, 2]
```

We can have array of ranges, in this case ranges are not expanded to the sequence they represent, there is nothing as the list comprehension of Python, and, to built an array of values from the range, the "to_a" method must be used.

a=[1..3,5...9] => [1..3, 5...9]

Some methods of ranges are in the following table:

 exclude_end? tests if last value is included: (1...3).exclude_end? => true cover? tests if between bounds: (1...3).cover?(2.5) => true include? ; member? tests if member of the range: (1...3).include?(3) => false begin the range begin: (1..3).begin => 1 end the range end: (1...3).end => 3 first(n) first n elements: (1..3).first(2) => [1, 2] last(n) last n elements (1..3).last(2) => [2, 3] min minimum value (1...3).min => 1 max maximum value: (1...3).max => 2 to_a converts to array: (1..3).to_a => [1, 2, 3] to_s string representation (1..3).to_s => "1..3"