Solidity 数组删除指定位置元素及指定位置新增元素

在使用Solidity开发智能合约时,免不了使用数组,但Solidity中的数组,只提供了pushpop方法来实现尾部新增和删除元素功能,这篇文章主要讲讲实际开发中怎么实现数组删除指定位置元素及指定位置新增元素。

一、数组删除指定位置元素

1. 默认delete操作符

java 复制代码
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

contract ArrayRemoveItem {
    uint[] public arr = [1,2,3,4,5];

    function remove(uint index) public {
        require(index < arr.length, "index not found");
        delete arr[index];
    }

    function getLength() public view returns(uint) {
        return arr.length;
    }
}

这种操作有个问题是,它会把指定位置的元素恢复默认值,如这里uint类型的默认值是0

我们执行remove(1)操作之后,arr的值为[1,0,3,4,5],并且执行getLength()值为5

这种方法的缺点是如果0本身在我们数组中是有意义的,那最终删除了之后值也是0就会导致最终的智能合约逻辑有问题。并且数组长度可能越来越长。

2. 和末尾元素交换位置,并删除末尾位置元素

java 复制代码
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

contract ArrayRemoveItem {
    uint[] public arr = [1,2,3,4,5];

    function remove(uint index) public {
        require(index < arr.length, "index not found");
        arr[index] = arr[arr.length - 1];
        arr.pop();
    }

    function getLength() public view returns(uint) {
        return arr.length;
    }
}

通过把末尾元素值先赋值给目标元素,再删除末尾元素实现删除目标元素的功能。

执行remove(1)操作后,arr的值为[1,5,3,4],执行getLength()值为4。

这种方法的缺点是我们删除中间一个元素后,数组的顺序会有变化,如果我们数组本身顺序是有意义的(如按照时间排序的),那最终也会导致我们智能合约逻辑有问题。

3. 目标元素后面所有元素向前移动一位

java 复制代码
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

contract ArrayRemoveItem {
    uint[] public arr = [1,2,3,4,5];

    function remove(uint index) public {
        require(index < arr.length, "index not found");
        for(uint i = index; i < arr.length - 1; i++) {
            arr[i] = arr[i + 1];
        }
        arr.pop();
    }

    function getLength() public view returns(uint) {
        return arr.length;
    }
}

要想删除目标元素也不改变原本数组位置,可以通过把目标元素后面所有元素向前移动一位,再删除最后一个元素来实现删除目标元素。

执行remove(1)后,arr的值为[1,3,4,5],并且执行getLength()值为4,得到的结果全是我们想要的。

但这种方法也有缺点,就是花费的gas费较高。

所以没有完美的方法,大家可以根据自己业务开发中实际需要选择,如果在你的业务中数组顺序无意义,推荐使用第二种方法(和尾部元素交互位置,删除位置元素),如果你的业务中是数组顺序有意义,推荐使用第三种方法。

二、指定位置新增元素

java 复制代码
// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;

contract ArrayRemoveItem {
    uint[] public arr = [1,2,3,4,5];

    function remove(uint index) public {
        require(index < arr.length, "index not found");
        for(uint i = index; i < arr.length - 1; i++) {
            arr[i] = arr[i + 1];
        }
        arr.pop();
    }

    function add(uint index, uint value) public {
        require(index < arr.length, "index not found");
        arr.push();
        for(uint i = arr.length - 1; i > index; i--) {
            arr[i] = arr[i - 1];
        }
        arr[index] = value;
    }

    function getLength() public view returns(uint) {
        return arr.length;
    }
}

指定位置新增元素的原理和上面删除差不多,先把新增一个空元素,然后把指定位置后面的所有元素向后移动一位,再把新值指定位置元素就完成了。

同样的缺点,消耗gas费较多哦。

这样就可以实现Solidity中数组删除指定位置元素和指定位置新增元素,具体选哪种方法,大家可以肯定自己实际业务需要选择。

相关推荐
长安链开源社区3 小时前
动手开发 | 如何通过k8s部署长安链
云原生·容器·kubernetes·区块链
长安链开源社区6 小时前
长安链开发大赛决赛入围名单揭晓
web3·区块链·共识算法
m0_380167147 小时前
加密货币数据 API 怎么选?(2026 全面指南)
区块链
程序员李程峰7 小时前
基础知识——各种钱包之间的联系与区别
web3·去中心化·区块链·智能合约·同态加密·零知识证明·信任链
程序员李程峰7 小时前
基础知识①区块链钱包基础
去中心化·区块链·智能合约·同态加密·共识算法·信任链·分布式账本
程序员李程峰7 小时前
基础知识②区块链的链是什么
web3·去中心化·区块链·智能合约·同态加密·共识算法·信任链
深念Y7 小时前
当加密遇见分布式:Web3、去中心化与元宇宙的底层逻辑
分布式·web3·去中心化·区块链·元宇宙·加密·价值
区块block1 天前
三分钟,快速了解区块链技术!
区块链
链上日记1 天前
Yesorno.ai公测启动:去中心化信息聚合市场进入全新发展阶段
去中心化·区块链
Turboex邮件分享1 天前
邮件系统中的区块链技术应用:安全与合规性
区块链