solidity – How to Return an Array of UINTS from a Struct – Complete Code Example

contract-developmentsolidity

I have a mapping that is storing bytes32=>uint. I want to write a function that loops through this mapping and only returns a list of the uints.

I know you cannot have a dynamic array in the function as it has to be in memory. But I need to store them in an array to be able to return the array in the function.

I just want all the ints to be returned in an array so I can access it on my frontend via JS.

This is what I have so far (that doesn't work):

function getAllVotes () returns (uint[]) {
    bytes32[] returnVotes;

    for(uint i = 0; i < candidateList.length; i++) {
      returnVotes[i] = bytes32(votesReceived[candidateList[i]]);
    }

    return returnVotes;

  }

Best Answer

Your unbounded for loop is an anti-pattern because it will cease to operate at scale when the gas cost exceeds the block gas limit. Ouch.

Break it up into multiple fixed-cost operations. Iteration is the caller's responsibility.

I also noticed you're declaring a storage variable inside a function. Not conventional. Below will give you "free" getters voteList(uint row) and voteStructs[bytes32 key]. The client can 1) get the list length, 2) get the keys one at a time, and 3) get the complete structure for any key.

contract Vote {

  struct VoteStruct {
    bool wasCast;
    // more stuff about votes
  }

  bytes32[] public voteList;
  mapping(bytes32 => VoteStruct) public voteStructs;

  function getVoteCount() public constant returns(uint voteCount) {
    return voteList.length;
  }   
}

In case it helps, there some patterns that combine mappings with key lists over here: Are there well-solved and simple storage patterns for Solidity?

Your snippet refers to a candidatesList and does some computation that you might want the smart contract to tally as the votes come in so you aren't tempted to iterate later.

Hope it helps.

Related Topic