是否有像 php 中的 foreach 那样的功能?

is there function like foreach from php in solidity?

这个很重要,所以当我做图的时候

mapping(address => uint256) balances;

我无法检查列表中的所有地址,如

foreach(balances as address => balance) log(address + ":" + balance + "\n");

所以如果我不将所有地址存储在排序数组中,我就不会访问该数组中的任何地址,所以目前我使用这个:

  mapping(address => uint8) joiners;
  address[] members;
...
  if (joiners[_to] >= 1) {
    joiners[_to] = 1;
    members.push(_to);
  }
  balances[_to] += _value;

那么我可以做到这一点

uint allbalances = 0;
for(uint i; i < members.length; i++) {
allbalances = balances[members[i]];
}
return allbalances;

但这很恶心,任何人都可以找到另一种解决方案,或者像 php 中的 foreach 一样运行??

此时,您无法从 solidity mapping 中检索所有密钥。

https://solidity.readthedocs.io/en/v0.4.24/types.html?highlight=mapping#mappings

我认为除非我们知道自己在做什么,否则最好避免合同中出现循环。我无法从你的问题中得到太多关于你试图实施的内容。如果您的目标是维持每个地址的余额以及总余额,我会做类似此处所示的事情。

contract Balance{

    mapping(address => uint) public balances;
    uint public totalBalance;

    function credit() payable public{
        balances[msg.sender] += msg.value;
        totalBalance += msg.value;
    }

    function debit(uint amount) public{
        //conditions
        require(balances[msg.sender] >= amount);

        //effects
        msg.sender.transfer(amount);
        balances[msg.sender] -= amount;
        totalBalance -= amount;
    }

}

即 - 每当您更新个人地址余额时更新 totalBalance。


根据评论部分的问题更新:

如果我们需要迭代所有的账户,那么我们需要单独维护密钥。我的观点是 - 与将利润分配给所有账户相比,调用总余额的频率要高得多。所以为了避免总余额计算的循环。

contract Ledger{

    address internal manager;
    mapping(address => uint) public balances;
    address[] public accounts;
    uint public totalBalance;

    constructor() public{
        manager = msg.sender;
    }

    function credit() payable public{
        if(balances[msg.sender] == 0){
            accounts.push(msg.sender);
        }

        balances[msg.sender] += msg.value;
        totalBalance += msg.value;
    }

    function debit(uint amount) public{
        //conditions
        require(balances[msg.sender] > amount);

        //effects
        msg.sender.transfer(amount);
        balances[msg.sender] -= amount;
        totalBalance -= amount;
    }

    function distributeProfit(uint amountToDistribute) public {
        require(manager == msg.sender);
        require(amountToDistribute > 0);

        //if profit might vary depends of balance, then place inside the loop.
        uint profit = amountToDistribute / accounts.length;

        for(uint index=0; index<accounts.length; index++){
            balances[accounts[index]] += profit;
        }
    }

 }