Is there a pop functionality for solidity arrays?

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[i] = myArray[i + 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.


Yes there is, as of v0.5.0 (details here):

Dynamic storage arrays and bytes (not string) have a member function called pop that you can use to remove an element from the end of the array. This also implicitly calls :ref:delete on the removed element.


You can try...

pragma solidity ^0.4.17;

contract TestArray {
   uint[] public items;

   constructor () public {
      items.push(1);
      items.push(2);
      items.push(3);
      items.push(4);
   }

   function pushElement(uint value) public {
      items.push(value);
   }

   function popElement() public returns (uint []){
      delete items[items.length-1];
      items.length--;
      return items;
   }

   function getArrayLength() public view returns (uint) {
      return items.length;
   }

   function getFirstElement() public view returns (uint) {
      return items[0];
   }

   function getAllElement()  public view returns (uint[]) {
      return items;
   }
}