Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a pop functionality for solidity arrays?

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 best solution for this ? How do I delete an element in a dynamic array in solidity ?

like image 742
Suraj Kohli Avatar asked Mar 01 '18 14:03

Suraj Kohli


People also ask

What is pop in Solidity?

4. Pop: Pop is used when the last element of the array is to be removed in any dynamic array. Example: In the below example, the contract Types first initializes an array[data], and then values are removed from the array using the pop function.

Are there arrays in Solidity?

In Solidity, an array can be of compile-time fixed size or of dynamic size. For storage array, it can have different types of elements as well.

How do I remove something from an array Solidity?

We can create a function remove() that will take an array's index as an argument. Then the function will set the index argument to the last element in the array. Simply, we will shift the index argument over the last element of the array. Then we will remove the last element by using the pop() method.


1 Answers

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.

like image 112
Adam Kipnis Avatar answered Sep 19 '22 13:09

Adam Kipnis