How to delete an element at a certain index in an array?

  • Anyone know how to delete an element in a array? Is there any built in method to do that?

    If not, does anyone know of how to implement such a method?

    Do you want to just delete the element, or delete it and move everything down an index?

    I would like everything down an index so if i delete a[2] then a[3] becomes a[2]

  • Tjaden Hess

    Tjaden Hess Correct answer

    5 years ago

    Use the delete operator to delete the element:

    delete array[index];
    

    If you don't want to leave a gap, you need to move each element manually:

    contract test{
        uint[] array = [1,2,3,4,5];
        function remove(uint index)  returns(uint[]) {
            if (index >= array.length) return;
    
            for (uint i = index; i<array.length-1; i++){
                array[i] = array[i+1];
            }
            delete array[array.length-1];
            array.length--;
            return array;
        }
    }
    

    If you don't care about the order, you can also just copy the last element into the empty spot, then delete the last element.

    Thanks! I just have an issue with the function you gave when trying to make it more " general : `function remove(uint[] array,uint index) returns(uint[]) {` gives me `Error: Expression has to be an lvalue. array.length--;` Also , does that method can be adapted to work on array of all types ( struct , etc ) ?

    I'm not sure about decreasing the length of arrays in memory, as opposed to storage. You can copy it all over to a new array, I guess, or just remove that line and leave the trailing zeros. You won't save any gas by making a memory array shorter, anyway. This method should work on any type, except mappings, since `delete` doesn't really make sense in mappings.

    if the array is very large for example 1000 objects, should not it consume very large amount of gas?

    @TjadenHess is it possible to delete a array member from another contract if the array is public? I know there are problems with that but I want to implement that. Thanks in advance.

    No, you can't do that out of the box. The other contract needs to provide some function for deleting array elements

    How could I delete the complete array?

    This function can leave the contract stalled if the array is very long.

    Decreasing array length will automatically clean up the storage slots occupied by the out-of-bounds elements. So the line `delete array[array.length-1];` is redundant. Moreover it adds 5000 gas to the transaction since gas refund applies only in the case when storage is reset from non-zero to zero value. If it's set from zero to zero (added by compiler) it costs 5000 gas.

    I wonder if it might be more efficient to use assembly somehow to shift pointers to avoid gap or concat a new array from the left and right sides of the gap

    Well, the correct way to do this would probably be to use a linked list instead of an array

    The best way I tested that works is to copy the last element to the deleted spot, call delete on the last index, then decrement the array length. This is a constant amount of work, not linear. If you care about the order, you should have an additional mapping from this element to next, that you maintain during addition and deletion.

License under CC-BY-SA with attribution


Content dated before 7/24/2021 11:53 AM