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中数组删除指定位置元素和指定位置新增元素,具体选哪种方法,大家可以肯定自己实际业务需要选择。

相关推荐
金融数据出海5 小时前
实时性、数据覆盖范围和易用性的优质金融数据源API推荐
后端·金融·区块链·ai编程
金融街小单纯8 小时前
随机刺激训练:解锁跨学科洞察力的科学密码
算法·重构·区块链
本郡主是喵18 小时前
基于区块链的电子投票系统的设计与实现(源码+文档)
区块链·毕业设计·solidity
leijiwen21 小时前
AI × RWA 本地生活品牌数字资产管理与增长平台
人工智能·web3·区块链
dingzd951 天前
Facebook受众挖掘的高效方法
web3·互联网·facebook·tiktok·instagram·指纹浏览器·clonbrowser
brave_zhao1 天前
业务知识:强制平仓
区块链
我菜我有理1 天前
使用python爬取BSC链上交易(玩具版)
区块链
taxunjishu2 天前
DeviceNet 转 Modbus TCP 协议转换在 S7-1200 PLC化工反应釜中的应用
运维·人工智能·物联网·自动化·区块链
酷柚易汛智推官2 天前
AI + 区块链开发实战:3 大技术方向 + 5 个落地案例,解锁去中心化网络效能密码
人工智能·去中心化·区块链
Django学习小组2 天前
CEX-DEX 稳定币套利模型
去中心化·区块链·比特币·套利·去中心化交易所