Solidity遍历
实际上,映射对于存储地址的标记值非常有用。 我们在许多合约中都看到了它们,它们通常以这种方式定义:
mapping (address => uint) public users;
由于映射是公共的,我们得到一个免费的getter,我们可以通过使用简单的方法获取myAddress的值
users(myAddress);
Solidity映射看起来可能类似于关联数组,但它不是,它没有索引,因此很难遍历所有地址。但它仍然可以通过其它方法遍历。
数组更容易管理:
address[] public addressIndices;
// start adding address in array
addressIndices.push(newAddress);
...
// We know the length of the array
uint arrayLength = addressIndices.length;
for (uint i=0; i<arrayLength; i++) {
// do something
}
假设我们想要计算所有地址的总值,拥有一组地址确实很有帮助。
mapping (address => uint) public mappedUsers;
address[] public addressIndices;
// start adding address in array
addressIndices.push(newAddress);
// define mappedUsers as well
mappedUsers[newAddress] = someValue;
...
// We know the length of the array
uint arrayLength = addressIndices.length;
// totalValue auto init to 0
uint totalValue;
for (uint i=0; i<arrayLength; i++) {
totalValue += mappedUsers[addressIndices[i]];
}
如果我们想要有效地删除数组怎么办? 我们必须将数组的最后位置移动到已删除的位置。
uint indexToBeDeleted;
mapping (address => uint) public mappedUsers;
address[] public addressIndices;
uint arrayLength = addressIndices.length;
for (uint i=0; i<arrayLength; i++) {
if (addressIndices[i] == addressToBeDeleted) {
indexToBeDeleted = i;
break;
}
}
// if index to be deleted is not the last index, swap position.
if (indexToBeDeleted < arrayLength-1) {
mappedUsers[indexToBeDeleted] = mappedUsers[arrayLength-1];
}
// we can now reduce the array length by 1
addressIndices--;
参考上面的代码,假设我们不希望for循环查找要删除的地址的索引,我们需要在结构中记录项的索引。 如果我们想要做一个合适的CRUD,它会变得有点复杂。
完整代码的示例参考如下:
pragma solidity^0.4.17;
contract Test {
struct structUser {
uint value;
uint index;
bool exists;
}
mapping(address => structUser) public arrayStructs;
address[] public addressIndexes;
function addAddress(uint _val) public returns (bool){
// if user exists, add _val
if (arrayStructs[msg.sender].exists > true) {
arrayStructs[msg.sender].value += _val;
}
else {
// else its new user
addressIndexes.push(msg.sender);
arrayStructs[msg.sender].value = _val;
arrayStructs[msg.sender].index = addressIndexes.length-1;
arrayStructs[msg.sender].exists = true;
}
return true;
}
function deleteAddress() public returns (bool) {
// if address exists
if (arrayStructs[msg.sender].exists) {
structUser memory deletedUser = arrayStructs[msg.sender];
// if index is not the last entry
if (deletedUser.index != addressIndexes.length-1) {
// delete addressIndexes[deletedUser.index];
// last strucUser
address lastAddress = addressIndexes[addressIndexes.length-1];
addressIndexes[deletedUser.index] = lastAddress;
arrayStructs[lastAddress].index = deletedUser.index;
}
delete arrayStructs[msg.sender];
addressIndexes.length--;
return true;
}
}
function getAddresses() public view returns (address[]){
return addressIndexes;
}
function getTotalValue() public view returns (uint) {
uint arrayLength = addressIndexes.length;
uint total = 0;
for (uint i=0; i<arrayLength; i++) {
total += arrayStructs[addressIndexes[i]].value;
}
return total;
}
function getTotalUsers() public view returns (uint) {
return addressIndexes.length;
}
}
代码来源地址:https://github.com/bernardpeh/solidity-loop-addresses-demo/blob/master/loop-demo.sol
文章来源:https://medium.com/@blockchain101/looping-in-solidity-32c621e05c22
Solidity遍历的更多相关文章
- [Contract] Solidity 遍历 mapping 的一种方式
思路:为需要遍历的 mapping 再准备一个 list,之后通过 for 循环遍历 list 取得 mapping 的 key. mapping (address => uint) users ...
- Solidity的地址 数组如何判断是否包含一个给定的地址?
Q: given address[] wallets. What is the correct method to check that the list contains a given addre ...
- 以太坊智能合约介绍,Solidity介绍
以太坊智能合约介绍,Solidity介绍 一个简单的智能合约 先从一个非常基础的例子开始,不用担心你现在还一点都不了解,我们将逐步了解到更多的细节. Storage contract SimpleSt ...
- Solidity合约:玉米生产溯源
实现思路: 首先用地址与每个结构进行映射,将关键信息储存在结构体中:或者将关键信息在外部通过json储存,内部储存对应的hash值: 使用issue函数表示:玉米地中收获足够数量的玉米并进行记录: 使 ...
- Solidity的delete操作
Solidity中有个特殊的操作符delete用于释放空间,因为区块链技术做为一种公用资源,为避免大家滥用.且鼓励主动对空间的回收,释放空间将会返还一些gas. delete关键字的作用是对某个类型值 ...
- Solidity数组
一.固定长度的数组(Arrays) 1.固定长度类型数组的声明 pragma solidity ^0.4.4; contract C { // 数组的长度为5,数组里面的存储的值的类型为uint类型 ...
- Solidity 官方文档中文版 2_Ethereum 智能合约介绍
一个简单的智能合约 先从一个非常基础的例子开始,不用担心你现在还一点都不了解,我们将逐步了解到更多的细节. Storage contract SimpleStorage { uint storedDa ...
- Solidity 文档--第一章:智能合约入门
一个简单的智能合约 先从一个非常基础的例子开始,不用担心你现在还一点都不了解,我们将逐步了解到更多的细节. 存储 contract SimpleStorage { uint storedData; f ...
- solidity智能合约中tx.origin的正确使用场景
简介 tx.origin是Solidity的一个全局变量,它遍历整个调用栈并返回最初发送调用(或事务)的帐户的地址.在智能合约中使用此变量进行身份验证会使合约容易受到类似网络钓鱼的攻击. 但针对tx. ...
随机推荐
- 【repost】Javascript操作DOM常用API总结
Javascript操作DOM常用API总结 文本整理了javascript操作DOM的一些常用的api,根据其作用整理成为创建,修改,查询等多种类型的api,主要用于复习基础知识,加深对原生js的认 ...
- Properties类、序列化流与反序列化流、打印流、commons-IO
Properties类 特点: 1.Hashtable的子类,map集合中的方法都可以用: 2.该集合没有泛型,键值都是字符串: 3.是一个可以持久化的属性集,键值可以存到集合中,也可存到持久化的设备 ...
- Eclipse怎么全局搜索和替换(整个项目)
我们用Eclipse编程,有时候需要将整个项目的某个字符串替换成其他的.那么我们该怎么操作呢?请接着往下看! 一,我们首先打开Eclipse,单击要替换字符串的项目 二,按下组合键:ctrl + H, ...
- php excel
项目中需要把excel转为索引数组,不输出key 只说下普世技巧 找了php excel插件 发现需要createReader方法,在sublime中search,可以搜索文件内容,找到使用creat ...
- AngularJS 杂项知识点
1.要用ngChange要同时使用ngModel,下拉选择获取当前选中值. 2.打包代替动态加载(js文件) requirejs真正的价值在于模块化,不是动态加载,angularjs本身有模块化机制, ...
- 在推送提交之后阻止Azure DevOps (TFS)持续集成
在Azure DevOps服务器上配置生成定义时,可以配置连续集成(CI)生成.每次签入或提交到源代码库时都会自动运行一个CI构建.这种机制允许开发人员启动一个自动化的过程,例如编译和部署构建.这是一 ...
- 记录一次错误处理 (xml序列化和反序列化相关)
XML序列化后,反序列化时出现错误 报错现象 System.InvalidOperationException: XML 文档(40, 11)中有错误. ---> System.Xml.XmlE ...
- ASP.NET MVC一次删除多笔记录 V2.0
前一段时间Insus.NET有写一篇<ASP.NET MVC一次删除多笔记录>http://www.cnblogs.com/insus/p/6241186.html 可以前往去看看. 觉得 ...
- DZY Loves Math(莫比乌斯反演)
\(x=p_1^{\alpha_1}p_2^{\alpha_2}...p_c^{\alpha_c}\) \(f(x)=\max(\alpha_1,\alpha_2,...,\alpha_c)\) \( ...
- 《UNIX环境网络编程》第十四章第14.9小结(bug)
1.源代码中的<sys/devpoll.h>头文件在我的CentOS7系统下的urs/include/sys/目录下没有找到. 而且我的CentOS7也不存在这个/dev/poll文件. ...