在Solidity智能合约开发中,数据结构的定义是非常重要的,下面介绍几种经常用到的数据结构。
Array(元素为Struct)
struct EntityStruct {
address entityAddress;
uint entityData;
// more fields
}
EntityStruct[] public entityStructs;
优点
- 可以保证按时间顺序排列
- 可以获得长度
- 可以通过数组下标随意取值
缺点
- 不能通过Id随机取值
- 不能保证唯一性
- 无法验证重复值
- 无法控制数组长度
例子:
pragma solidity ^0.4.6;
contract simpleList {
struct EntityStruct {
address entityAddress;
uint entityData;
// more fields
}
EntityStruct[] public entityStructs;
function newEntity(address entityAddress, uint entityData) public returns(uint rowNumber) {
EntityStruct memory newEntity;
newEntity.entityAddress = entityAddress;
newEntity.entityData = entityData;
return entityStructs.push(newEntity)-1;
}
function getEntityCount() public constant returns(uint entityCount) {
return entityStructs.length;
}
}
Mapping(Id => Struct)
struct EntityStruct {
uint entityData;
bool isEntity;
}
mapping (address => EntityStruct) public entityStructs;
优点
- 可以通过Id取值
- Id唯一
- 内部可以包含 arrays, mappings和structs
缺点
- 无法按照key遍历
- 无法获得元素的数量
- 元素的值默认是0,如果要区分当前值为0的时候是否是默认值,需要额外的逻辑检查
例子:
contract mappingWithStruct {
struct EntityStruct {
uint entityData;
bool isEntity;
}
mapping (address => EntityStruct) public entityStructs;
function isEntity(address entityAddress) public constant returns(bool isIndeed) {
return entityStructs[entityAddress].isEntity;
}
function newEntity(address entityAddress, uint entityData) public returns(bool success) {
if(isEntity(entityAddress)) throw;
entityStructs[entityAddress].entityData = entityData;
entityStructs[entityAddress].isEntity = true;
return true;
}
function deleteEntity(address entityAddress) public returns(bool success) {
if(!isEntity(entityAddress)) throw;
entityStructs[entityAddress].isEntity = false;
return true;
}
function updateEntity(address entityAddress, uint entityData) public returns(bool success) {
if(!isEntity(entityAddress)) throw;
entityStructs[entityAddress].entityData = entityData;
return true;
}
}
Array(元素为Struct) + Mapping(Id => bool)
struct EntityStruct {
address entityAddress;
uint entityData;
}
EntityStruct[] public entityStructs;
mapping(address => bool) knownEntity;
优点
- 可以通过数组下标随意取值
- Id唯一
- 内部可以包含 arrays, mappings和structs
缺点
- 不能通过Id随机取值
- 无法控制数组长度
例子:
contract arrayWithUniqueIds {
struct EntityStruct {
address entityAddress;
uint entityData;
}
EntityStruct[] public entityStructs;
mapping(address => bool) knownEntity;
function isEntity(address entityAddress) public constant returns(bool isIndeed) {
return knownEntity[entityAddress];
}
function getEntityCount() public constant returns(uint entityCount) {
return entityStructs.length;
}
function newEntity(address entityAddress, uint entityData) public returns(uint rowNumber) {
if(isEntity(entityAddress)) throw;
EntityStruct memory newEntity;
newEntity.entityAddress = entityAddress;
newEntity.entityData = entityData;
knownEntity[entityAddress] = true;
return entityStructs.push(newEntity) - 1;
}
function updateEntity(uint rowNumber, address entityAddress, uint entityData) public returns(bool success) {
if(!isEntity(entityAddress)) throw;
if(entityStructs[rowNumber].entityAddress != entityAddress) throw;
entityStructs[rowNumber].entityData = entityData;
return true;
}
}
Mapping(Id => Struct)+ Array(元素为Id)
struct EntityStruct {
uint entityData;
bool isEntity;
}
mapping(address => EntityStruct) public entityStructs;
address[] public entityList;
优点
- 可以通过Id数组下标随意取值
- Id唯一
- 内部可以包含 arrays, mappings和structs
- 保留了元素声明的顺序
- 可以获得元素数量
- 可以通过Id遍历
- 通过设置布尔值来删除元素
缺点
- 无法控制数组长度
例子:
contract MappedStructsWithIndex {
struct EntityStruct {
uint entityData;
bool isEntity;
}
mapping(address => EntityStruct) public entityStructs;
address[] public entityList;
function isEntity(address entityAddress) public constant returns(bool isIndeed) {
return entityStructs[entityAddress].isEntity;
}
function getEntityCount() public constant returns(uint entityCount) {
return entityList.length;
}
function newEntity(address entityAddress, uint entityData) public returns(uint rowNumber) {
if(isEntity(entityAddress)) throw;
entityStructs[entityAddress].entityData = entityData;
entityStructs[entityAddress].isEntity = true;
return entityList.push(entityAddress) - 1;
}
function updateEntity(address entityAddress, uint entityData) public returns(bool success) {
if(!isEntity(entityAddress)) throw;
entityStructs[entityAddress].entityData = entityData;
return true;
}
}
Mapping(Id => Struct)+ Array(元素为Id)+ 删除功能
struct EntityStruct {
uint entityData;
uint listPointer;
}
mapping(address => EntityStruct) public entityStructs;
address[] public entityList;
优点
- 可以通过Id数组下标随意取值
- Id唯一
- 内部可以包含 arrays, mappings和structs
- 可以获得元素数量
- 可以通过Id遍历
- 通过设置布尔值来删除元素
- 可以通过删除函数控制剩余元素的数量
缺点
- 增加了代码复杂度
- 增加存储成本
- 元素是无序的
例子:
contract mappedWithUnorderedIndexAndDelete {
struct EntityStruct {
uint entityData;
uint listPointer;
}
mapping(address => EntityStruct) public entityStructs;
address[] public entityList;
function isEntity(address entityAddress) public constant returns(bool isIndeed) {
if(entityList.length == 0) return false;
return (entityList[entityStructs[entityAddress].listPointer] == entityAddress);
}
function getEntityCount() public constant returns(uint entityCount) {
return entityList.length;
}
function newEntity(address entityAddress, uint entityData) public returns(bool success) {
if(isEntity(entityAddress)) throw;
entityStructs[entityAddress].entityData = entityData;
entityStructs[entityAddress].listPointer = entityList.push(entityAddress) - 1;
return true;
}
function updateEntity(address entityAddress, uint entityData) public returns(bool success) {
if(!isEntity(entityAddress)) throw;
entityStructs[entityAddress].entityData = entityData;
return true;
}
function deleteEntity(address entityAddress) public returns(bool success) {
if(!isEntity(entityAddress)) throw;
uint rowToDelete = entityStructs[entityAddress].listPointer;
address keyToMove = entityList[entityList.length-1];
entityList[rowToDelete] = keyToMove;
entityStructs[keyToMove].listPointer = rowToDelete;
entityList.length--;
return true;
}
}
Hi! I am a robot. I just upvoted you! I found similar content that readers might be interested in:
https://ethereum.meta.stackexchange.com/questions/443/blog-simple-storage-patterns-in-solidity
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit
Congratulations @ljyxxzj! You received a personal award!
You can view your badges on your Steem Board and compare to others on the Steem Ranking
Vote for @Steemitboard as a witness to get one more award and increased upvotes!
Downvoting a post can decrease pending rewards and make it less visible. Common reasons:
Submit