0

Solidity enables the use of associative arrays with mapping:

mapping(address => uint256) balances;

Code can be written to iterate through this associative array. But, how can all of the keys and values be outputted onto a terminal, webpage or downloadable file?

  • You can write a contract method to return data. Use truffle console to invoke the method to display result on console, use web3 api to display result on webpage. – Abhishek Aug 4 '17 at 6:42
4

"Solidity enables the use of associative arrays with mapping:

mapping(address => uint256) balances; Code can be written to iterate through this associative array."

I don't think we have an pre-defined iterator that loops through the mapping in solidity. The answer is from the link below, where an index is introduced to loop through the mapping.

https://forum.ethereum.org/discussion/1995/iterating-mapping-types

mapping (address => uint) accountBalances;
mapping (uint => address) accountIndex;
uint accountCount;
function iterateAccountsBalances()
{
    for(uint i=0;i<accountCount;i++)
    {
        doSomeStuff(accountBalances[accountIndex[i]]);
    }
}

In the above case accountIndex is the Index that makes sequential access possible.

But, how can all of the keys and values be outputted onto a terminal, webpage or downloadable file?

There are different ways to do it,you can either connect your contract with Web3 if you need it web and if its console you could possibly use truffle console.

1

Rangesh show a main point, and then i get a simple demo. At first, we create a simple contract MappingTest

contract MappingTest {

  CustomMap balances;

  struct CustomMap {
     mapping (address => uint) maps;
     address[] keys;
  }

  function put() payable public {
     address sender = msg.sender;
     uint256 value = msg.value;
     bool contain = contains(sender);
     if (contain) {
       balances.maps[sender] = balances.maps[sender] + value;
     } else {
       balances.maps[sender] = value;
       balances.keys.push(sender);
     }
  }

  function iterator() constant returns (address[],uint[]){
      uint len = balances.keys.length;
      address[] memory keys = new address[](len);
      uint[] memory values = new uint[](len);
      for (uint i = 0 ; i <  len ; i++) {
         address key = balances.keys[i];
         keys[i] = key;
         values[i] = balances.maps[key];
      }
      return (keys,values);
  }

  function remove(address _addr) payable returns (bool) {
      int index = indexOf(_addr);
      if (index < 0) {
          return false;
      }
      delete balances.maps[_addr];
      delete balances.keys[uint(index)];
      return true;
  }

  function indexOf(address _addr) constant returns (int) {
    uint len = balances.keys.length;
    if (len == 0) {
        return -1;
    }
    for (uint i = 0 ; i < len ;i++) {
      if (balances.keys[i] == _addr) {
          return int(i);
      }
    }
    return -1;
  }

  function contains(address _addr) constant returns (bool) {
      if (balances.keys.length == 0) {
         return false;
      }
      uint len = balances.keys.length;
      for (uint i = 0 ; i < len ; i++) {
          if (balances.keys[i] == _addr) {
            return true;
          }
      }
      return false;
  } 

}

and then compile, deploy contract by geth. Now, we unlock account and then execute put function

browser_test_sol_mappingtest.put({from:eth.accounts[0],value:web3.toWei(1,'ether')})
browser_test_sol_mappingtest.put({from:eth.accounts[1],value:web3.toWei(1,'ether')})

now, there are two txs waitting for mined, then execute mine op

miner.start(1);admin.sleepBlock(1);miner.stop()

two txs was packed to new block, now we execute interator function to show result

> browser_test_sol_mappingtest.iterator()
[["0x0b46c35d2e823f9b1e69ff616f9e9bf2d9d52dd0", "0xc4b232913cb195f649086d1eea0f1eb3fd0ff825"], [1000000000000000000, 1000000000000000000]]

It's same to remove, contains, indexOf function.

For JSON RPC , How to call a contract method using the eth_call JSON-RPC API will give you detail step.

Hope this helps you ~

  • Thanks for such an elaborate answer. Am I correct to assume these?: 1) It can be outputted to terminal or web, but not a downloadable file; 2) Your code would not be able to extract data from an existing contract's mapping variable. That is, it is not possible to create a 2nd contract with your code to extract data from the 1st contract's mapping variable. Your code needs to be included in the 1st contract. – Curt Aug 4 '17 at 14:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.