Solidity 数组中删除特定位置元素和插入新元素的操作

Solidity 数组中删除特定位置元素和插入新元素的操作

电报联系方式

Solidity 智能合约开发中,数组是不可避免的数据结构之一。然而,Solidity数组仅提供了push和pop方法用于在尾部进行元素的添加和删除。本文旨在讨论如何在实际开发中实现对数组中特定位置元素的删除和新增

Solidity 数组中删除特定位置元素和插入新元素的操作

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

1. 默认delete操作符

// 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. 和末尾元素交换位置,并删除末尾位置元素

// 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. 目标元素后面所有元素向前移动一位

// 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 费用相对较高。因此,没有一种方法是完美的。开发者可以根据实际业务需求选择适合自己的方法。如果数组顺序在业务中无意义,建议使用第二种方法(与尾部元素交换位置,然后删除目标位置元素)。如果数组顺序在业务中具有意义,则推荐使用第三种方法。

二、指定位置新增元素

// 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消耗太多。

开发联系:DEXDAO

 

 

© 版权声明

相关文章

暂无评论

暂无评论...