Solidity遍历

Posted flyingeagle

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Solidity遍历相关的知识,希望对你有一定的参考价值。

  实际上,映射对于存储地址的标记值非常有用。 我们在许多合约中都看到了它们,它们通常以这种方式定义:

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

以上是关于Solidity遍历的主要内容,如果未能解决你的问题,请参考以下文章

solidity智能合约中tx.origin的正确使用场景

Solidity零基础入门Solidity编写智能合约代码

Solidity零基础入门Solidity编写智能合约代码

Solidity零基础入门Solidity编写智能合约代码

Solidity零基础入门Solidity编写智能合约代码

用于字节操作的 Solidity 代码无法使用 Solidity 0.8.0 的安全帽编译器进行编译