11

For example following code piece from https://ethereum.stackexchange.com/a/10763/4575 . I have added new lines that is followed by //*.

pragma solidity ^0.4.2;
contract test {    
  struct my_struct {
    int a;
    int my_length; //*to keep track of the length.
  }

  mapping (address=>my_struct[]) Map;

  function fill_map(my_struct struct1,my_struct struct2) internal  {    
    Map[msg.sender].push(struct1);
    Map[msg.sender][0].my_length = Map[msg.sender][0].my_length + 1;//*

    Map[msg.sender].push(struct2);   
    Map[msg.sender][0].my_length = Map[msg.sender][0].my_length + 1;//*

    Map[msg.sender].push(struct3);//*  
    Map[msg.sender][0].my_length = Map[msg.sender][0].my_length + 1;//*

    delete Map[id][2]; //*struct3 will be removed.
    Map[msg.sender][0].my_length = Map[msg.sender][0].my_length - 1;//*
  }
}

I can obtain data as follows: Map[id][index].a; index is an integer number. In this example it can be 0 (for struct1) or 1 (for struct2).

As we know Java could return the number of object inside a list:

String[] array = new String[10];
int size = array.length;

Is there anything similar as: Map[id].length ? or manually after each push or delete should I need to keep length?

On my solution Map[msg.sender][0].my_length will return the number of the pointed structs from Map[msg.sender].

alper
  • 8,395
  • 11
  • 63
  • 152

3 Answers3

7

You can't get the number of mapped keys or get a list of keys that map to data.

You can maintain a list a keys in a separate array as you insert data into a map and then you can get the count indirectly by asking how long the index is.

If you use event emitters to report state changes, you can often proceed on the idea that the contract itself doesn't need the count or the list and the clients don't need further help from the contract.

Rob Hitchens
  • 55,151
  • 11
  • 89
  • 145
  • 1
    Whoa, the question changed a lot. I'm confused about what we're trying to accomplish. We would be able to figure out how many structs are stored at a give address map (array of structs), but not how many addresses have structs. Hope that makes sense. – Rob Hitchens Dec 23 '16 at 18:12
5

there is some mistakes (or i didn't understand well your question) in your previous code and i think also in your question.

in your case you have a map of arrays. so Map[key].length exists and return the size of the corresponding array to your key. so Map[msg.sender].length is correct but Map[msg.sender][0].length is not. because in this second case you are returning the first struct which doesn't have a length parameter but a my_length.

Badr Bellaj
  • 18,780
  • 4
  • 58
  • 75
  • 1
    Ahh my bad, I am sorry for the confusion. I did not know Map[key].length actually exists, so I try to use variable my_length to keep track. It was a typo Map[msg.sender][0].my_length is the correct line. – alper Dec 23 '16 at 18:25
2

I understood the question as if you can get the length of mapping or not, in case you were, the following statement will NOT work:

Map.length

Unfortunately, mappings in Solidity are not iterable and don't have length or count properties as you can read from the official documentation here.

One solution is to keep track of the size manually by declaring a state variable and increase/decrease it whenever you have a push/delete operation on the mapping.

The code will be something like this:

uint mapSize;
// after a push operation
mapSize++;
// after a delete operation
mapSize--;

You need to know that the map size cannot be used to index the map you have even when you have the key as uint and you have to know that this process will make you use more GAS.