An array is a data structure where multiple values of similar data types can be stored.
In contrast, a struct works as a container of a group of elements of different data types. A struct can then also be considered as a new data type.
Hence we can create an array of structs comprising those new data types.
Most Solidity programmers eventually wonder: How to return an array of structs from a function?
Today, we will create an array of structs and find a way to return it from a function.
Creating a Struct and Adding Features
letβs create a contract named SavingsAccount
for Finxter committee members.
pragma solidity ^0.8.0; pragma experimental ABIEncoderV2; contract SavingsAccount { struct Member{ uint id; string name; uint balance; } mapping (uint => Member) public members; event savingsEvent(uint indexed _memberId); uint public memberCount;
- The standard ABI encoder specification does not permit arrays of dynamic types, structs, or nested variables between the Solidity contract and the dApp. Thatβs why we used an experimental version
ABIEncoderV2
, that allows structs, nested, and dynamic variables to be used as parameters into functions. - We have created a struct for each member of the committee. It consists of the memberβs ID, name and balance.
- We have created a mapping with key type “
uint
β and value type βMember
β to store the values. The mapping works like a dictionary in Python or a map in Javascript. Unlike Python, we canβt iterate through mapping or quickly get its size. We have to do some extra coding for iteration. - An event named β
savingsEvent
” is added to monitor any state changes occurring inside the contract continuously. The smart contract will automatically get notifications when a new member is added to the committee. - β
indexed
β keyword is used as a parameter inside thesavingsEvent
to get the specific events where the parameter equals to_memberId
.
constructor() public { memberCount = 0; addMember("chris",9000); addMember("yassin",6000); } function addMember(string memory _name, uint _balance) public { members[memberCount] = Member(memberCount,_name,_balance); memberCount++; }
- A constructor is created to count the number of members from zero. Two new members have already been added to the constructor. We can make as many members as we like from the constructor.
- The
addMember()
function takes the new memberβs name and balance as arguments and adds it to the constructor. It also increases the number of members when a new member joins the committee.
Let’s add a new member to check if all the functions are working correctly. We will add a new member named “adam
β and set his balance to 8000.
We deployed the contract and added a member named βadam
β. Then we clicked the “memberCount
” button to check how many members were on the committee. It came up with a result “3” since we have added a new member in the committee with βchris
β and βyassin
β. So, all are working fine.
How to Return a Single Structure?
It is possible to return a memberβs information using the following function. we can use the _memberID
as the id of the member and let it return the information of that structure as a tuple.
function get(uint _memberId) public view returns(Member memory) { return members[_memberId]; }
- The
get()
function takes the_memberId
as an argument and returns the structure information of that member as a tuple.
As we tried to return the information of the id number 1, it returns the info of Yassin because the member count starts from 0. From the tuple, we can see member id is 1, member name is yassin, and the balance is 6000.
How to Return the Value of a Structure?
If we want to return individual arrays of ID, name and balance from the structure information that is also possible with another function. letβs jump in:
function getMember() public view returns (uint[] memory, string[] memory,uint[] memory){ uint[] memory id = new uint[](memberCount); string[] memory name = new string[](memberCount); uint[] memory balance = new uint[](memberCount); for (uint i = 0; i < memberCount; i++) { Member storage member = members[i]; id[i] = member.id; name[i] = member.name; balance[i] = member.balance; } return (id, name,balance); }
- The
getMember()
function returns each field of the member as an individual array - We have declared three new memory arrays with β
memberCount
β, representing the length of each memory array. As thememberCount
increases with the addition of a new member, we can consider it as the array’s length. - Using the for loop, we iterate through the “
members
” array and populate it with the member’s id, name, and balance. - The β
return
β expression returns individual arrays of the memberβs id, name and balance.
When we deployed the contract and clicked the “getMember
” button, we got three arrays of id, name, and balance for all the members of the finxter committee.
How to Return an Array of Structures?
We have got the information of all the members in multiple arrays from the above method. But what happens if we try to return all the information of the members in a single array. Is it possible in Solidity?
It’s a bit tricky, but it’s possible in a way. The getMembers()
function allows us to achieve that.
function getMembers() public view returns (Member[] memory){ Member[] memory id = new Member[](memberCount); for (uint i = 0; i < memberCount; i++) { Member storage member = members[i]; id[i] = member; } return id; } }
- The
getMembers()
function returns all the info of the structs in an array - A new memory array named β
id
β is created with βnew Member[](memberCount
)”. - For loop iterates through each struct of the “
members
” array and gathers the information in a single array. - The β
return
β keyword returns an array with all the memberβs info included
As we clicked the “getMembers
” button, we got all the member’s info in an array. It shows the id, name, and balance in a sequence.
For your convenience I published the code on GitHub. You may get it here:
That’s all for today. There are other methods available on the web to get the desired answer. But I found the above a good fit. If you are interested in some more solutions like this, you can check the following links of StackOverflow.
References:
- https://ethereum.stackexchange.com/questions/3589/how-can-i-return-an-array-of-struct-from-a-function/97517
- https://stackoverflow.com/questions/47028165/how-do-i-return-an-array-of-struct-from-a-function
Programmer Humor
β Question: Why do programmers always mix up Halloween and Christmas?
β Answer: Because Oct 31 equals Dec 25.
(If you didn’t get this, read our articles on the oct()
and int()
Python built-in functions!)