实际上,映射对于存储地址的标记值非常有用。 我们在许多合约中都看到了它们,它们通常以这种方式定义:
mapping (address => uint) public users;
由于映射是公共的,我们得到一个免费的getter,我们可以通过使用简单的方法获取myAddress的值
users(myAddress);
Solidity映射看起来可能类似于关联数组,但它不是,它没有索引,因此很难遍历所有地址。但它仍然可以通过其它方法遍历。
数组更容易管理:
address[] public addressIndices; // start adding address in array addressIndices.push(newAddress); ... // We know the length of the array uint arrayLength = addressIndices.length; for (uint i=0; i<arrayLength; i++) { // do something }
假设我们想要计算所有地址的总值,拥有一组地址确实很有帮助。
mapping (address => uint) public mappedUsers; address[] public addressIndices; // start adding address in array addressIndices.push(newAddress); // define mappedUsers as well mappedUsers[newAddress] = someValue; ... // We know the length of the array uint arrayLength = addressIndices.length; // totalValue auto init to 0 uint totalValue; for (uint i=0; i<arrayLength; i++) { totalValue += mappedUsers[addressIndices[i]]; }
如果我们想要有效地删除数组怎么办? 我们必须将数组的最后位置移动到已删除的位置。
uint indexToBeDeleted; mapping (address => uint) public mappedUsers; address[] public addressIndices; uint arrayLength = addressIndices.length; for (uint i=0; i<arrayLength; i++) { if (addressIndices[i] == addressToBeDeleted) { indexToBeDeleted = i; break; } } // if index to be deleted is not the last index, swap position. if (indexToBeDeleted < arrayLength-1) { mappedUsers[indexToBeDeleted] = mappedUsers[arrayLength-1]; } // we can now reduce the array length by 1 addressIndices--;
参考上面的代码,假设我们不希望for循环查找要删除的地址的索引,我们需要在结构中记录项的索引。 如果我们想要做一个合适的CRUD,它会变得有点复杂。
完整代码的示例参考如下:
pragma solidity^0.4.17; contract Test { struct structUser { uint value; uint index; bool exists; } mapping(address => structUser) public arrayStructs; address[] public addressIndexes; function addAddress(uint _val) public returns (bool){ // if user exists, add _val if (arrayStructs[msg.sender].exists > true) { arrayStructs[msg.sender].value += _val; } else { // else its new user addressIndexes.push(msg.sender); arrayStructs[msg.sender].value = _val; arrayStructs[msg.sender].index = addressIndexes.length-1; arrayStructs[msg.sender].exists = true; } return true; } function deleteAddress() public returns (bool) { // if address exists if (arrayStructs[msg.sender].exists) { structUser memory deletedUser = arrayStructs[msg.sender]; // if index is not the last entry if (deletedUser.index != addressIndexes.length-1) { // delete addressIndexes[deletedUser.index]; // last strucUser address lastAddress = addressIndexes[addressIndexes.length-1]; addressIndexes[deletedUser.index] = lastAddress; arrayStructs[lastAddress].index = deletedUser.index; } delete arrayStructs[msg.sender]; addressIndexes.length--; return true; } } function getAddresses() public view returns (address[]){ return addressIndexes; } function getTotalValue() public view returns (uint) { uint arrayLength = addressIndexes.length; uint total = 0; for (uint i=0; i<arrayLength; i++) { total += arrayStructs[addressIndexes[i]].value; } return total; } function getTotalUsers() public view returns (uint) { return addressIndexes.length; } }
代码来源地址:https://github.com/bernardpeh/solidity-loop-addresses-demo/blob/master/loop-demo.sol
文章来源:https://medium.com/@blockchain101/looping-in-solidity-32c621e05c22