对于Solidity新手来说,简单合适的使用数据结构去组织数据是一个挑战。对于区块链上的数据组织,是否有简单而通用的模式来帮助我们链上数据?
以下是一些简单而有用的模式,按常用性递增顺序排列。
为简洁起见,省略了事件日志。 在实践中,希望为每个重要的状态变化发出事件。
优点
缺点
举例:
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;
}
}
优点
缺点
举例:
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;
}
}
优点
按下标(行号)随机访问
保证Id的唯一性
用每个“记录”包含数组,映射和结构体
Random access by Row number
Assurance of Id uniqueness
Enclose arrays, mappings and structs with each "record"
缺点
举例:
contract arrayWithUniqueIds {
struct EntityStruct {
address entityAddress; // 唯一ID
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;
}
}
优点
缺点
举例:
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;
}
}
优点
缺点
2019 更新
在 Solidity 0.5.1,这个模式已经有一个库实现Solidity 实现增删改查-博客 UnorderedKeySet GitHub库
举例:
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;
}
}
还有一个Solidity 双向链表 :linkedList.sol
问答由深入浅出区块链社区成员整理。
深入浅出区块链 - 系统学习区块链,学区块链的都在这里,打造最好的区块链技术博客。