7

I have a struct and I'd like to remove an item by index:

struct Payout {
  address addr;
  uint yield;
}

Payout[] public payouts;

I'm not familiar with structs and more use to dealing with arrays in javascript where I would do something like this:

payouts.splice(index, 1);

What's the best way to do this with a struct array in Solidity?

Edit: Would also like array to shift down like with the splice function. E.g. when you delete payouts[0] the data from payouts[1] shifts back into its spot.

  • Or you can make flag that tells if contract was removed. – Satosi Ethemoto Apr 7 '16 at 11:48
3

You can simply do:

function deletePayoutYield() {
    delete payout.yield;
}

Or in a array:

function deletePayoutYield(uint index) {
    delete payoutArray[index].yield;
}

function deletePayout(uint index) {
    delete payoutArray[index];
}
  • I would want to delete both yield and address and causes all other entries ahead to fall back one in their index. Can I expect that behaviour if I do 'delete payoutArray[index];' ? – Philip Kirkbride Apr 7 '16 at 8:58
  • Yes, I'll edit the answet with that case – arodriguezdonaire Apr 7 '16 at 9:05
  • I think with the code you posted the data at payoutArray[index] is deleted but the array doesn't fall back. So if I delete payoutArray[0] it will sit as an empty spot with no data rather then payoutArray[1] taking its place. – Philip Kirkbride Apr 7 '16 at 10:51
  • I don't think delete does what we want it to do. The array won't be reorganized. – Rob Hitchens - B9lab Mar 30 '17 at 2:13
2

I found that javascript's splice could easily be replicated by setting structs[index] data to equal the data of the last item in the array. Then cut the length by one. If I understand correctly the data from the last item in the array is deleted when the length is subtracted from :

  payouts[index] = payouts[payouts.length-1];
  payouts.length = payouts.length -1;

Edit: this is working for what I need but it doesn't actually solve my original question as it doesn't maintain the order of the array like splice would. Maybe there is no easy way to do without manually looping through?

1

From what I can recall, in most languages, arrays are implemented as contiguous blocks in memory, so splicing out an element would require re-indexing every element afterwards (essentially, a linear-time operation).

If you wanted to retain the order of the list after removing an element, consider using a linked hashmap instead of an array: this would allow you to get constant-time access to your elements by a key (not index), and removal would be constant-time as well (as long as you know the key of the element being removed).

0

It's not (currently) possible to delete a random row from an ordered array in a gas-efficient way.

There are two commonplace approaches to handling a logical delete. In the case that deletes are few and far between, it can sometimes suffice to set a flag that indicates expired (removed) entries and then logically skip them as one iterates over the list.

struct MyStruct {
  uint field1; 
  uint field2;
  bool isActive;
}

MyStruct[] public myStructs;

This maintains the list in the order of declaration but it doesn't control growth of the list.

You can control the growth of the list and do a gas-efficient logical delete at the expense of list order. You move the last item in the list to the row you want to delete. That keeps the gas cost consistent at any scale.

enter image description here

To support that, you need some pointers in the data structure.

enter image description here

In practice, the unordered nature of the list shouldn't be important in most use-cases. A minimalist approach to Smart Contracts inclines to contracts that ensure the integrity of the data. Ordered access is usually a concern that be safely separated from Smart Contract logic.

A more complete walk-through with example implementation here: https://medium.com/@robhitchens/solidity-crud-part-2-ed8d8b4f74ec

Some other simpler examples here: Are there well-solved and simple storage patterns for Solidity?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.