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. ...
随机推荐
- 发邮件、排序、FIFO
发送邮件.py: import smtplib from email.mime.text import MIMEText def email(receiver, title='标题', b ...
- Mysql 分区(range,list,hash)转载
MySQL支持RANGE,LIST,HASH和KEY四种分区.其中,每个分区又都有一种特殊的类型.对于RANGE分区,有RANGE COLUMNS分区.对于LIST分区,有LIST COLUMNS分区 ...
- CentOS中自动加载802.1q模块
要想在CentOS中自动加载内核模块,需要在/etc/sysconfig/modules/目录中增加一个脚本,在此脚本中加载所需的模块. 下面是我所用的一个名为8021q.modules的脚本,用来在 ...
- ZOJ 1259 Rails
stack的应用 #include<iostream> #include<cstdio> #include<stack> using namespace std; ...
- linux常用命令(一)linux开关机、重启以及文本界面与图形界面互换
1.开关机 reboot 重启: shutdown [-efFhknr][-t 秒数][时间][警告信息] 关机: shutdown [-efFhknr][-t 秒数][时间][警告信息] 关机: - ...
- Android开发教程 - 使用Data Binding(七)使用BindingAdapter简化图片加载
本系列目录 使用Data Binding(一)介绍 使用Data Binding(二)集成与配置 使用Data Binding(三)在Activity中的使用 使用Data Binding(四)在Fr ...
- AJPFX外汇的常见形态
AJPFX:外汇价常见形态 外汇的价格,本质上是由供求关系决定的,但是在技术分析的世界里,是什么原因导致供求关系的改变并不重要,也没有人能准确的找出所有的因素并加以判断,但是供求关系被改变后的外汇走势 ...
- UCore-Lab1
日期:2019/3/31 内容:makefile分析: 一."Makefile"分析 1.1 ucore.img lab1已有的源文件 目录 文件 boot asm.h.boo ...
- 201621123018《java程序设计》第12周作业总结
1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2. 面向系统综合设计-图书馆管理系统或购物车 使用流与文件改造你的图书馆管理系统或购物车. 2.1 简述如何 ...
- [学习笔记]Splay
其实就是一道题占坑啦 [NOI2005]维护数列 分析: 每次操作都要 \(Splay\) 一下 \(Insert\) 操作:重建一棵平衡树,把 \(l\) 变成根,\(l+2\) 变成右子树的根,那 ...