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 小时前
Crypto加密货币生态构成及较有前景的几个crypto项目
区块链
秋说19 小时前
【区块链安全 | 第八篇】多签机制及恶意多签
安全·区块链
CryptoPP1 天前
基于WebSocket的金融数据实时推送系统架构设计对接多国金融数据API
websocket·网络协议·金融·系统架构·区块链
浪子小院1 天前
区块链技术之分布式数字身份:构建数字世界的信任基石
区块链
秋说1 天前
【区块链安全 | 第十七篇】类型之引用类型(一)
安全·区块链
网络研究院1 天前
身份验证:区块链如何让用户掌控一切
去中心化·区块链·身份·隐私·技术·验证·数字
尽-欢1 天前
以太坊DApp开发脚手架:Scaffold-ETH 2 详细介绍与搭建教程
react.js·typescript·web3·区块链
区块链蓝海1 天前
Cooker.club:AI虚拟偶像与Web3的奇妙碰撞
人工智能·区块链
YSGZJJ1 天前
股指期货的行情在哪看?怎么看行情表?
区块链
gdjwr654651 天前
Macro 巨汇黄金外汇投资全解析:策略与操作步骤?
金融·区块链