[CryptoZombies - 2 Solidity Advanced] 005 For loop

table of Contents

I. Introduction

Two, For loop

1, introduction

2, For loop

3, combat

1. Requirements

2. Code


I. Introduction

Read some block chain of tutorials, papers, on the Internet just to find a project combat, CryptoZombies.

Earlier we talked about Gas, today we'll look at in terms of how to conserve Gas.

If you want to learn more about machine learning, deep learning, block chain, computer vision and other related technologies, to communicate with more chiefs, then scan the next Fanger Wei code to join us now!

Two, For loop

1, introduction

In order to achieve  getZombiesByOwner the function, one solution is  ZombieFactory stored in the "master" and "zombie army" of the map.

mapping (address => uint[]) public ownerToZombies

Then each time you create a new zombie when you need to perform ownerToZombies [owner] .push(zombieId) to add it to the owner of the zombie array. The  getZombiesByOwner function is also very simple:

function getZombiesByOwner(address _owner) external view returns (uint[]) {
  return ownerToZombies[_owner];
}

This approach is really very simple, very direct, but it is a problem:

What happens if we need a function to put a zombie transferred to another owner name (we will achieve in a later lesson)?

The owner of the replacement operations need to achieve:

1. Zombie push to the new owner of the  ownerToZombies array.

2.From the old master  ownerToZombies to remove zombie array.

3. Each former team head zombie after zombie array "for the main zombie," the all move forward one, left behind after the move to go "for the main zombie" "empty slot" to fill.

4. The array length minus 1.

The third step but it is too expensive! Because each move a zombie, we have to perform a write operation. If the owner has a 20 zombies, and the first head was moved away, and that in order to maintain order of the array, we have to do 19 write operations. Since the write operation Solidity storage is one of the most expensive gas, so that the main function of the change are very expensive each call. Worse, gas every time it takes to call is different! DETAILED position also depends on the number of users in the legion of origin zombie head, and removed where the zombies. So that users do not know how much gas should be paid.

It is said that we can put an array of zombies in a last move forward to fill the empty slot, and a reduction in the length of the array. But so that each do a deal, we will change the order of the zombie army.

Because a call from the external  view function is free, we can also in  getZombiesByOwner a for loop through the array of zombies with function, the zombies belong to a lord singled out to construct an array of zombies. Then our  transfer function will be much cheaper, because we do not need to move stored in an array of zombies reordering, this method generally will be cheaper, though a bit counter-intuitive.

2, For loop

In order to achieve the above functions, we have to use a for loop. for circulation for all of us, if learned other programming languages, it is quite familiar.

We look at a simple example:

function getEvens() pure external returns(uint[]) {
  uint[] memory evens = new uint[](5);
  // 在新数组中记录序列号
  uint counter = 0;
  // 在循环从1迭代到10:
  for (uint i = 1; i <= 10; i++) {
    // 如果 `i` 是偶数...
    if (i % 2 == 0) {
      // 把它加入偶数数组
      evens[counter] = i;
      //索引加一, 指向下一个空的‘even’
      counter++;
    }
  }
  return evens;
}

This function returns a form of  [2,4,6,8,10] array.

3, combat

1. Requirements

We are getZombiesByOwner a function by  for circulating DApp to traverse all zombies given 'user id' to each head zombie 'master' are compared, and before the function returns push them to our result array.

1. Declare a variable  counter, attribute  uint, set its value  0 . We use this variable as  result the array index.

2.Declare a  for loop, from  uint i = 0 to  i <zombies.length. It will loop through the array in each head zombies.

3. In each round  for the loop, with a  if statement to check  zombieToOwner [i] whether equal  _owner. This compares two addresses match.

4. In the  if statement:

  (1) By  result [counter] setting  ithe ID added to the zombie  result array.

  (2) the counter is incremented.

In this way - this function can return  _owner a zombie array have, without spending a penny gas.

2. Code

pragma solidity >=0.5.0 <0.6.0;

import "./zombiefeeding.sol";

contract ZombieHelper is ZombieFeeding {

  modifier aboveLevel(uint _level, uint _zombieId) {
    require(zombies[_zombieId].level >= _level);
    _;
  }

  function changeName(uint _zombieId, string calldata _newName) external aboveLevel(2, _zombieId) {
    require(msg.sender == zombieToOwner[_zombieId]);
    zombies[_zombieId].name = _newName;
  }

  function changeDna(uint _zombieId, uint _newDna) external aboveLevel(20, _zombieId) {
    require(msg.sender == zombieToOwner[_zombieId]);
    zombies[_zombieId].dna = _newDna;
  }

  function getZombiesByOwner(address _owner) external view returns(uint[] memory) {
    uint[] memory result = new uint[](ownerZombieCount[_owner]);
    // Start here
    uint counter = 0;
    for(uint i = 0; i < zombies.length; i++) {
      if(zombieToOwner[i] == _owner) {
        result[counter] = i;
        counter++;
      }
    }
    return result;
  }

}
Published 266 original articles · won praise 525 · views 530 000 +

Guess you like

Origin blog.csdn.net/shuiyixin/article/details/104490487