Is there a pop functionality for solidity arrays?

前端 未结 3 1091
失恋的感觉
失恋的感觉 2021-02-20 10:36

I have used solidity to push data into an array. Is there a similar function for pop ?

string[] myArray;
myArray.push(\"hello\")

What is the be

3条回答
  •  名媛妹妹
    2021-02-20 11:17

    Update 2-19-2019: As Joel pointed out below, pop has been added to built-in array support. See https://solidity.readthedocs.io/en/v0.5.4/types.html#array-members. Leaving original answer on here in case others are using older versions of Solidity.


    There is no pop function in Solidity. You have a few options you can consider for maintaining your array.

    Delete & Leave Gaps

    The simplest solution is to just delete the element at a specific index:

    string element = myArray[index];
    delete myArray[index];
    return element;
    

    However, this will NOT shift the elements in your array and will leave an element of "string 0" in your array. To check this element, you would use

    if(bytes(myArray[index]).length > 0) ...

    Swap & Delete

    If you don't care about order in your array, you can swap the element with the last element in your array and then delete:

    string element = myArray[index];
    myArray[index] = myArray[myArray.length - 1];
    delete myArray[myArray.length - 1];
    myArray.length--;
    return element;
    

    Delete With Shift

    If order in your array is important, you can delete the element then shift all remaining elements to the left.

    string element = myArray[index];
    for (uint i = index; i < myArray.length - 1; i++) {
      myArray[index] = myArray[index + 1];
    }
    delete myArray[myArray.length - 1];
    myArray.length--;
    return element;
    

    Note that this will be the most expensive of the options. If your array is very long, you will have high gas usage.

    Correlating with @Jedsada's suggestion, here is a version as a library:

    pragma solidity ^0.4.24;
    
    library StackLib {
      using StackLib for Stack;
    
      struct Stack {
        uint[] _items;
      }
    
      function pushElement(Stack storage self, uint element) internal returns (bool) {
        self._items.push(element);
      }
    
      function popElement(Stack storage self) internal returns (uint) {
        uint element = self.peek();
    
        if (self.size() > 0)
          delete self._items[self.size() - 1];
    
        return element;
      }
    
      function peek(Stack storage self) internal returns (uint) {
        uint value;
    
        if (self.size() > 0)
          value = self._items[self.size() - 1];
    
        return value;
      }
    
      function size(Stack storage self) internal returns (uint8) {
        return self.size();
      }
    }
    

    Example usage (Important note: You can't use popElement and return the value to a client. That method changes state and should only be used within a transaction.):

    contract Test {
      using StackLib for StackLib.Stack;
    
      StackLib.Stack numbers;
    
      function add(uint v) public {
        numbers.pushElement(v);
      }
    
      function doSomething() public {
        for (uint8 i = 0; i < numbers.size(); i++) {
          uint curNum = numbers.popElement();
    
          // do something with curNum
        }
      }
    }
    

    Additional note: Unfortunately, var has been deprecated since 0.4.20 and there is no replacement for generics. You have to customize for a specific type.

提交回复
热议问题