Array is a data structure widely used in programming languages. It is a collection of values, and in Solidity it is a collection of values of the same type.
For instance, an integer array is a collection of integer values. A string array is a collection of values of type string. The collection is ordered, so that each value is placed in a certain location (we call it an index) in the array.
There are two types of arrays in solidity: the static array and the dynamic array. In the static array, the number of stored values is defined at the time of array declaration. As for the dynamic array, the total number of values is not defined and it is possible to add new values on the fly.
Let’s start by creating an array of type uint, as in the code below.
uint[5] staticArray;
The array created above is a static array, and we defined that it will store 5 values of type uint. To create a dynamic array, just don’t include the size of the array, as in the statement below.
uint[] dynamicArray;
Static arrays are initialized at the time of their declaration. The variable staticArray contains 5 values of type uint and these 5 values are initialized with the default value of 0.
Dynamic arrays, if uninitialized, assume an initial size of 0 items. Each new item in the dynamic array is then initialized when it is added to the array.
Initializing arrays
It is possible to initialize arrays while declaring their values. The declaration below initializes the static array with its 5 values.
uint[5] staticArray = [10, 20, 30, 40, 50];
The same goes for dynamic arrays.
uint[] dynamicArray = [10, 20, 30, 40, 50];
Both arrays now have 5 items stored, however we can add new items to the dynamic array, while the static array does not receive new items. All we can do with it is change the value of its items.
There is another way to initialize arrays, using the new constructor. Let’s see this in the statement below.
uint[] dynamicArray = new uint[](5);
As a result, the first five items in the array are initialized to their default value. It is not possible to use the new constructor with static arrays, nor would it make sense, as their items are already initialized at declaration time.
Arrays in memory
Arrays in memory behave differently than arrays in storage. Once the space they will occupy in memory is defined, this space cannot be stretched. That is, it is not possible to create dynamic arrays in memory.
The code below, inside a function, is valid, but innocuous.
uint[] memory newArray;
A dynamic array was created in memory, but as it was not initialized, its size is 0. As it cannot be enlarged, its size will always be 0.
To create a new array in memory, it must either be declared as a static array or as a dynamic array with a constructor. Both ways are shown in the code below.
uint[3] memory staticArrayMemory;
uint[] memory dynamicArrayMemory = new uint[](3);
Managing arrays
It is possible to change arrays using literals. As we have already seen, literal is the representation of a type. The array literal is a set of values, enclosed in square brackets, separated by a comma. In the code below, we use a literal to change the array.
dynamicArray = [1, 2, 3, 4, 5, 6, 7];
The variable dynamicArray was an array in the storage that we initialized with 5 items. Now we change this variable to store an array of 7 items. As it is a dynamic array, there is no problem. If it was a static array, the compiler would throw an error.
It is more common to change individual values in the array. To have access to an item in the array, we use square brackets, as follows.
dynamicArray[3] // access to the fourth item in the array
As the index of the arrays starts counting at 0, the index 3 corresponds to the fourth item. To change the value of the array corresponding to the index, just assign the value like any other variable.
dynamicArray[3] = newValue;
Dynamic arrays have two manipulation methods. The push() method adds a new element after the last item in the array, as follows.
dynamicArray.push(6) // includes a new item of value 6 at the end of the array
The pop() method removes the last item from the array. Both push() and pop() change the size of the array. It is also possible to change a given array index to its default value using the delete operator, as follows.
delete dynamicArray[3] // makes the value of index 3 return to its default value
Note that the delete operator does not delete the item, it just changes its value. The result of the above operation would be the same as assigning the value 0 to dynamicArray[3].
Arrays have the length property, which returns their size.
Special arrays
Solidity has 2 types which are basically special arrays: string and bytes. Arrays are reference types, so string and bytes are as well.
We can think of strings as an array of characters, but it’s actually an array of bytes. Its behavior is not the same as a dynamic array. We cannot apply the push and pop operators to a string, for example, and the length property does not even exist in strings.
The manipulation of strings in Solidity is not as simple as in most other programming languages, but there are external libraries that help us in this work.
The type bytes is also a special type of array, an array of bytes. It has a similarity to the array bytes1[], which is explicitly an array of type 1-byte, but the type bytes takes up less memory.
In the following code, I will show the use of the type bytes, just as I will show that the string type is an array of bytes.
function stringToBytes() public view returns(bytes memory) {
string memory name = unicode"João";
bytes memory nameToBytes = bytes(name);
return nameToBytes;
}
Inside the function, I first create a string in memory. I need to use the prefix unicode so that Solidity accepts the accent of the letter ‘a’. Then I create a variable of type bytes, which will receive the bytes of the variable of type string. For this, we need to convert the variable from type string to type bytes. The function return can be seen in the figure below.
What is this return? It is the string ‘João’ encoded in UTF-8, the standard that Solidity uses. There are several websites where you can easily encode/decode string to UTF-8. In the figure below, I use one of these sites as an example.
The bytes type is more malleable than the string type, as it accepts the use of methods like push and pop. Let’s see the code below.
bytes public name = unicode"Joã";
function bytesAsStrings() public {
bytes1 letter = 0x6f;
name.push(letter);
}
The bytes type accepts strings as an assignment value, and Solidity converts strings to UTF-8 automatically. Note that the function adds a new byte to the array, equivalent to the letter ‘o’. This would not be possible using the string type.
We will work more with arrays as the course progresses.
Thanks for reading!
Comments and suggestions about this article are welcome.
Any contribution is welcome. www.buymeacoffee.com/jpmorais
New to trading? Try crypto trading bots or copy trading
Learn Solidity lesson 14. Arrays. was originally published in Coinmonks on Medium, where people are continuing the conversation by highlighting and responding to this story.