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

相关推荐
Wnq100721 小时前
去中心化分布式计算与云计算的性能对比研究
云计算·去中心化·区块链
Biteagle17 小时前
Movement 新公链机制解析:下一代区块链的创新与突破
区块链
TechubNews17 小时前
Aave V4:从割裂市场到模块化流动性
区块链
Biteagle17 小时前
REE白皮书发布:比特币如何突破可编程性瓶颈?
区块链·智能合约
焦点链创研究所19 小时前
BUYCOIN:打造社区共治的去中心化新标杆
去中心化·区块链
木西19 小时前
第一价格密封拍卖智能合约全流程实现指南
web3·智能合约·solidity
公链开发19 小时前
CEX开发困局:当达普韦伯为交易所注入“数字灵魂”
区块链
MicroTech202521 小时前
微算法科技(NASDAQ MLGO)基于区块链的网络化协同设计数据存储与管理方案
科技·区块链
焦点链创研究所1 天前
Fusaka升级对以太坊都有哪些好处?
人工智能·科技·web3·去中心化·区块链
公链开发1 天前
Web3双核引擎:当AI量化金融大脑,遇见DAO社交生态灵魂
区块链