How to return mapping list in Solidity? (Ethereum contract)
Asked Answered
C

4

25

I want to make a simple smart contract that has a list, can set item, and can get the list.

Code in solidity:

contract lister {
    mapping(int => string) list;
    int id = 0;
    
    function getList() returns ( /*HERE*/ ) {
        return list;
    }

    function setItemToList(string str) {
        list[id] = str;
        id++;
    }
}

I want to make getList() return the list, but the return type is not compatible. How can I do that?

Cardin answered 3/6, 2016 at 5:52 Comment(0)
P
23

Bulk access to lists/arrays/etc is painful in Solidity. You rarely see it in contracts. In your case, a possible solution is to provide a function to access one item, using its index, and to let the caller loop from 0 to id.

Polychromatic answered 5/6, 2016 at 16:6 Comment(2)
I believe the answer to this question is yes. In fact you can see which sites do this since they will be accessible without metamask installed.Epicurus
I am still looking for an answer to this, and so far, it seems the only way to get access to the entire list without executing a for loop/rate limited, is to process transaction/event history and store the data myself... which means I need to keep the data in sync at all times between my own storage and the blockchain...Questor
S
8

With mappings, keys are not stored and the values can not be iterated upon, so they are really only good for single-value lookups. In the example you provide, it may be a better choice to use an array.

On the other hand, if you use an array and need to do a search on it (loop through all items), you need to be careful because if there are too many items in your array, it could end up costing a considerable amount of gas to call the function.

Sachs answered 19/1, 2018 at 22:49 Comment(0)
E
3

You can change the visibility of your variable list, insert public and it will possible to access this by getList.

mapping(int => string) public list;

Earthly answered 25/1, 2018 at 21:13 Comment(3)
you should not do this. This makes map available to any one. So they can access the map without knowing key values.Peyter
@Peyter It looks like OP wants to make the map available to anyone. Is there any other reason this is bad practice, or just bad if you want to keep it private?Daunt
does this make anyone able to edit it ?Tasse
A
0

Mappings do not store their keys, only the value which is stored at the state memory address. To get the list of data use an array.

address[] public addresses;

now define a function to get the length of this array:

   function getAddressCount() public view returns(uint){
        return addresses.length;
    }

Also define a function to get the element by index:

function getAddressByIndex(uint index) public view returns(address){

   return addresses[index]
}

now u need to write code to pull the get the array one by oen. This is how it is done in javascript with web3 library:

let addresses,addressCount;
try {
     addressesCount = await ContractName.methods.getCampaignCounts().call();
       
    addresses = await Promise.all(
      Array(parseInt(addressesCount))
        .fill()
        .map((element, index) => {
          return ContractName.methods.getAddressByIndex(index).call();
        })
    );
    
  } catch (e) {
    console.log("error in pulling array list", e);
  }
Arlie answered 1/1, 2022 at 22:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.