DEV Community

Agoi Abel Adeyemi
Agoi Abel Adeyemi

Posted on

4 1

Array and Map in Solidity

alt array and map in solidity

An array allows us to represent a collection of data, but it is often more useful to think of an array as a collection of variables of the same type with keys having sequential order based on the order they were added.

Instead of declaring individual variables, such as number1, number2, number3, ….., and number99, you can declare one array variable such as numbers and use numbers[0], numbers[1], …, numbers[99] to represent individual variables.

Having understood how the array works in JAVASCRIPT and PHP, I was going to rush through it in solidity but to my greatest surprise, it is quite different here in the solidity blockchain world :). I decided to write about the array and map since both of them seem similar to me and can be used together.

Unlike in javascript where we could have an array of integer together with strings or any other data type, our array must have the variable of the same data type and this can be enforced when declaring it like below:

uint[] myArray; //declaring an array of integer variables

Before I dive fully into the array in solidity, I want to clarify that there are two types of arrays in solidity, which are the storage array and the memory array.

Storage Array:

These are arrays that are stored inside the blockchain after you execute your function, you can declare them like normal variables without our contract like below:

pragma solidity ^0.5.3;
contract Array {
uint[] intergerArray; //sample showing initialization of an array of integers
bool[] boolArray; //sample showing initialization of an array of booleans
address[] addressArray; //sample showing initialization of an array of address etc.
}
view raw array_map.sol hosted with ❤ by GitHub

where unit/bool/address is the variable type, followed by [] and then the name of the array which can be any name.

Manipulation of the storage array:

To add a new element to the array, we need to reference the array and use the .push(value), we can also update an array position by referencing the element key like myArray[0] = ‘new value’;, we also can also get a particular array element position by simple using myArray[0] where 0 is the index or key of the array element

pragma solidity ^0.5.3;
contract{
uint[] myArray;
function manipulateArray() external {
myArray.push(1); // add an element to the array
myArray.push(3); // add another element to the array
myArray[0]; // get the element at key 0 or first element in the array
myArray[0] = 20; // update the first element in the array
//we can also get the element in the array using the for loop
for (uint j = 0; j < myArray.length; j++) {
myArray[j];
}
}
}

We can also use the for loop to access the element of the array as we would array in javascript (also in the snippet above). To delete an element in the array, we will use delete myArray[1] where 1 is the array key, please note that this will not affect the array length but will only reset the array value at the index of one or second element in the array to the default value of the data type. i.e 0 if it’s a uint type and false if bool. When we try to access an array key that does not exist, we will have an error.

Memory Array:

These arrays are not stored into the blockchain after calling the function, you can only declare them within a function like below:

pragma solidity ^0.5.3;
contract MemoryArray {
/**
* These are temporary arrays and only exists when you are executing a function
* Must have a fixed size and must be declared inside a function
* You cannot run a for loop in a memory array
*/
function memoryArray() public {
uint[] memory newArray = new uint[](10);
}
}

where unit[] is the type of the variables, memory keyword declares it has a memory array followed by the name which can be an acceptable name, it must be equated to new unit type where the unit[] must be the variable type again and the number of elements that will be in the array in the bracket ().

Manipulation of the memory array:

To add value to the memory array, we cannot use the .push() method, as we need to use the index notation instead like newArray[0] = 1 , newArray[1] = 1 etc. We can read a value, update a value, delete a value from the memory array just like the storage array.

Passing an array as a function argument:

We can pass an array as a function argument in solidity, the function visibility determines if the keyword before the array name should be calldata or memory. We use calldata if the function visibility is external and memory if the function visibility is public and internal. See example below:

pragma solidity ^0.5.3;
contract ArraySolidity {
/** Visible external */
function functionExternal(uint[] calldata myArg) external returns(uint[] memory) {
uint[] memory newArray = new uint[](10);
newArray[0] = 1;
return newArray;
}
/** Visible public */
function functionPublic(uint[] memory myArg) public returns(uint[] memory) {
uint[] memory newArray = new uint[](10);
newArray[0] = 1;
return newArray;
}
}

Seems we have covered all we need to do in an array, how about mapping.

A Map is something like an array with a collection of similar variables that uses key look-ups meaning you’re referencing values with an object instead of an integer in short.

Basically, mapping is equivalent to a dictionary or a map in other programming languages. It’s key-to-value storage. A standard array is an index look-up e.g. if there are 10 elements in the array the indexes are 0–9 and it would look like below as an array of integers:

[0] 555
[1] 123
...
[8] 22
[9] 5

The map works slightly different and the easiest way to describe it is that it uses key lookups. So if this was a map of addresses to integers then it would look something like:

[0x000000000000000A] 555
[0x0000000000000004] 123
....
[0x0000000000000006] 22
[0x0000000000000003] 6

So basically, you’re referencing values with an object instead of an integer. The keys also don’t have to be in sequence. It consists of two main parts: a _KeyType and a _ValueType; they appear in the following syntax below:

mapping (_KeyType => _ValueType) mapName.

Think of the _KeyType as the key you'll pass through a function to return the desired value, or _ValueType. By default, a mapping is initially empty, so a new _KeyType will first need to be mapped to a _ValueType.

It could be

mapping(string => string) mapName;

Or

mapping(int => bool) mapName;

Manipulation of a map:

We can manipulate a map within a function like below:

pragma solidity ^0.5.3;
contract Mapping {
mapping(address => uint) balances;
function manipulateMap() external {
balances[msg.sender] = 100; //assign a value;
balances[msg.sender] //read a value;
balances[unknown_key] //will return the default value of the type, i.e 0 for uint
}
}
view raw gistfile1.txt hosted with ❤ by GitHub

We assigned a value to the map here balances[msg.sender] = 100 by equating it to a value. We read the value also by balances[msg.sender] without assigning any value. When we use a non-existence key to read a value from a map, it will return the default data value used to initialize the value type when declaring it unlike undefined in javascript.

Assign an array as a map value:

We can assign an array as a value type to a map and can access them as we would an array like below:

pragma solidity ^0.5.3;
contract Mapping {
mapping(address => uint[]) scores;
function manipulateArrayMap() external {
scores[msg.sender].push(1); //assign a value;
scores[msg.sender].push(2); //assign another element
scores[msg.sender][0]; //access the element in the map array
scores[msg.sender][1] = 5; //update an element in the map array in index 1
delete scores[msg.sender][0]; //delete the element in the index 0 of the map array
}
}

Assign another map as a map value:

We can also assign another map as a map value and can access them as we would access a map like below:

pragma solidity ^0.5.3;
contract Mapping {
mapping(address => uint) balances;
mapping(address => mapping(address => bool)) approved;
function manipulateMapOfMap(spender) external {
approved[msg.sender][spender] = true //assign a value to the approved map
approved[msg.sender][spender]; //get the value of the map
delete approved[msg.sender][spender] //delete the reference
}
}

We can assign a Struct as a map value type too, there are occasions when you want to iterate over a map and do other things on a map, I would advise you check out the resources below when the need arises:

Guide

Guide

Guide

AWS GenAI LIVE image

How is generative AI increasing efficiency?

Join AWS GenAI LIVE! to find out how gen AI is reshaping productivity, streamlining processes, and driving innovation.

Learn more

Top comments (0)

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay