11

I've got the following simple contract:

pragma solidity ^0.4.24;

contract MyContract {

  struct Person {
    uint age;
    uint size;
  }

  // Index of a person is its ID.
  Person[] persons;

  event PersonAdded(uint indexed id, uint age, uint size);

  function addPerson(uint _age, uint _size) public {
    Person memory person = Person(_age, _size);
    id = persons.push(person) - 1;

    emit PersonAdded(id, _age, _size)
  }

  function removePerson(uint _id) public {
    // Something like the following would be ideal:
    // require(persons.hasKey(_id), "Person does not exist.")

    delete persons[_id]
  }
}

How can I check if the given key exists in the persons array?

3 Answers 3

11

You can use an explicit exists field:

pragma solidity ^0.4.24;

contract MyContract {

  struct Person {
    uint age;
    uint size;
    bool exists;
  }

  // Index of a person is its ID.
  Person[] persons;

  event PersonAdded(uint indexed id, uint age, uint size);

  function addPerson(uint _age, uint _size) public {
    Person memory person = Person(_age, _size, true);
    id = persons.push(person) - 1;

    emit PersonAdded(id, _age, _size);
  }

  function removePerson(uint _id) public {
    require(persons[_id].exists, "Person does not exist.");

    delete persons[_id];
  }
}
2
  • Very smart, thank you! Even though, this only helps if you have Struct values. What about basic types?
    – haggis
    Commented Aug 11, 2018 at 8:03
  • 2
    Basic types can always be wrapped in a struct. Or you could have a separate bool[] exists. There's no concept of "existence" in Solidity: just zeros and non-zeros.
    – user19510
    Commented Aug 11, 2018 at 10:26
1

you can try to parse the array as following :

  function exist (uint age_, uint size_) view returns (bool){
      for (uint i; i< persons.length;i++){
          if (persons[i].age==age_ && persons[i].size==size_)
          return true;
      }
  }
2
  • 1
    Thanks for your answer. However, this only works if the combination of the properties is unique (which is not secured). Also, this could lead to enourmos gas cost on huge datasets. This doesn't solve the problem.
    – haggis
    Commented Aug 10, 2018 at 18:45
  • in this case use a mapping instead. or add some conditions a unique identifiant
    – Badr Bellaj
    Commented Aug 10, 2018 at 18:47
0

Even though that's far from ideal (because it causes additional gas cost), this is how I do it now:

pragma solidity ^0.4.24;

contract MyContract {

  struct Person {
    uint age;
    uint size;
  }

  // Index of a person is its ID.
  Person[] persons;


  // The following holds a list of currently existing persons (without holes between the indexes)
  uint256[] personIds;

  // Holds the mapping from personID to its index in the above personIds array.
  mapping (uint256 => uint256) personIdToIndex;

  modifier personExists(uint256 _id) {
    uint256 index = personIdToIndex[_id]; // is 0 if not explicitly set
    require(personIds[index] == _id, "Person does not exist.");

    _;
  }

  event PersonAdded(uint indexed id, uint age, uint size);

  function addPerson(uint _age, uint _size) public {
    Person memory person = Person(_age, _size);
    id = persons.push(person) - 1;

    uint256 key = personIds.push(id) - 1;
    personIdToIndex[id] = key;

    emit PersonAdded(id, _age, _size)
  }

  function removePerson(uint _id) personExists(_id) public {
    delete persons[_id]

    // Reorganize index array and map
    uint256 key = personIdToIndex[_id];

    // Fill gap with last element of personIds
    personIds[key] = personIds[personIds.length - 1];

    // Update personIdToIndex
    personIdToIndex[personIds[key]] = key;

    // Decrease length of personIds array by 1
    personIds.length--;
  }
}

I won't mark this as the correct answer for now, because I still hope there's a more elegant solution.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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