映射是一种引用类型,存储键值对。它的定义是:mapping(key => value),概念上与java中的map,python中的字典类型类似,但在使用上有比较多的限制。

一.mapping定义
  在mapping中, key可以是整型、字符串等基本数据类型,但不能使用动态数组、contract、枚举、struct,以及mapping这些类型。 value 的类型没有限制,甚至使用一个mapping作为value也是允许的。

pragma solidity ^0.4.24;

contract Mappings {
struct Employee {
string name;
uint8 no;
}
mapping (bytes => Employee) bytesMapping; //字节数组作为key
mapping (address => Employee) addressMapping; // address作为key
mapping (string => mapping(uint => Employee)) complexMapping; // mapping作为value,是可以的。
// mapping (Employee ==> uint8) structMapping; //不能使用struct来作为key function len() public returns(uint8) {
// 编译错误: TypeError: Member "length" not found or not visible after argument-dependent lookup in mapping(bytes memory => struct Mappings.Employee // storage ref)
// return bytesMapping.length;
// ^-----------------^
}
}

  在solidity中,mapping可以看做是一个哈希表。 在这个表中,已经列举了所有可能的key值,并把这些key映射到已经将所有字段初始化为0的value上。 但在存储上,key的值并不是直接保存在这个哈希表中,而是它的keccak256值。使用的时候,需要通过这个值来查到对应的真实的key值。 所以,在solidity中,mapping没有长度length的概念,也无法使用set来设置或者添加映射值的必要。

二.存储模型
  到当前版本,mapping 还仅能被声明为storage变量中,不能使用在memory上。 由于在mapping中键的数量是任意的,导致映射的大小也是变长的。映射只能声明为storage的状态变量, 或者在局部变量中引用到某个状态变量。

pragma solidity ^0.4.24;

contract Mappings {
struct Employee {
string name;
uint8 no;
}
mapping (bytes => Employee) bytesMapping; function declaring() public returns(string) {
bytesMapping["alex"] = Employee("Alex John", 1);
mapping (bytes => Employee) ref = bytesMapping;
ref["alex"].name = "Alexanda Jackson";
return bytesMapping["alex"].name;
}
}

  如上我们声明了bytesMapping的状态变量,然后在函数中申明ref局部变量来引用它。

三.mapping状态变量
  如果在contract中声明了mapping状态变量, solidity编译器会自动生成get方法, 输入参数为key,输出参数为value。 如果使用mapping来作为value,则会生成两个输入参数的get方法, 以此类推。

pragma solidity ^0.4.24;

contract Mappings {
struct Employee {
string name;
uint8 no;
}
mapping (string => mapping(uint8 => Employee)) complexMapping; function setter() public returns(string){
complexMapping["alex"][1] = Employee("Alex John", 1);
complexMapping["alex"][2] = Employee("Alex Mike", 2);
complexMapping["tom"][1] = Employee("Tom Cruise", 6);
return complexMapping["tom"][1].name;
}
}

  在上面的示例中,我们声明了storage的状态变量complexMapping,可以使用key来访问或者设置对应的值。

四.mapping扩展
  由于原生的mapping限制比较多, 以太坊在官方的github上提供了一个扩展IterableMapping库 。 增加了类似其他语言的映射类型的操作。

library IterableMapping
{
struct itmap
{
mapping(uint => IndexValue) data;
KeyFlag[] keys;
uint size;
}
struct IndexValue { uint keyIndex; uint value; }
struct KeyFlag { uint key; bool deleted; }
function insert(itmap storage self, uint key, uint value) returns (bool replaced)
{
uint keyIndex = self.data[key].keyIndex;
self.data[key].value = value;
if (keyIndex > 0)
return true;
else
{
keyIndex = self.keys.length++;
self.data[key].keyIndex = keyIndex + 1;
self.keys[keyIndex].key = key;
self.size++;
return false;
}
}
function remove(itmap storage self, uint key) returns (bool success)
{
uint keyIndex = self.data[key].keyIndex;
if (keyIndex == 0)
return false;
delete self.data[key];
self.keys[keyIndex - 1].deleted = true;
self.size --;
}
function contains(itmap storage self, uint key) returns (bool)
{
return self.data[key].keyIndex > 0;
}
function iterate_start(itmap storage self) returns (uint keyIndex)
{
return iterate_next(self, uint(-1));
}
function iterate_valid(itmap storage self, uint keyIndex) returns (bool)
{
return keyIndex < self.keys.length;
}
function iterate_next(itmap storage self, uint keyIndex) returns (uint r_keyIndex)
{
keyIndex++;
while (keyIndex < self.keys.length && self.keys[keyIndex].deleted)
keyIndex++;
return keyIndex;
}
function iterate_get(itmap storage self, uint keyIndex) returns (uint key, uint value)
{
key = self.keys[keyIndex].key;
value = self.data[key].value;
}
}

  使用示例如下:

contract User
{
// Just a struct holding our data.
IterableMapping.itmap data;
// Insert something
function insert(uint k, uint v) returns (uint size)
{
// Actually calls itmap_impl.insert, auto-supplying the first parameter for us.
IterableMapping.insert(data, k, v);
// We can still access members of the struct - but we should take care not to mess with them.
return data.size;
}
// Computes the sum of all stored data.
function sum() returns (uint s)
{
for (var i = IterableMapping.iterate_start(data); IterableMapping.iterate_valid(data, i); i = IterableMapping.iterate_next(data, i))
{
var (key, value) = IterableMapping.iterate_get(data, i);
s += value;
}
}
}

文章来源:https://toutiao.io/posts/vg6mip/preview

Solidity之mapping类型的更多相关文章

  1. 检测空值,以及会不会出现mapping类型不一致的问题

    /// <summary> /// 检测空值,以及会不会出现mapping类型不一致的问题 /// </summary> /// <typeparam name=&quo ...

  2. ES7.x mapping 类型

    在将ES从2.3 升级到7.3版本的过程中,mapping是一个过不去的坎,很多类型都发生了变化 7.x常用数据类型:text.keyword.number.array.range.boolean.d ...

  3. [Contract] Solidity 判断 mapping 值的存在

    比如 mapping(address => uint) tester,只需要判断 mapping 是否为默认值 0, tester[msg.sender] == 0 "You can ...

  4. [Contract] Solidity 遍历 mapping 的一种方式

    思路:为需要遍历的 mapping 再准备一个 list,之后通过 for 循环遍历 list 取得 mapping 的 key. mapping (address => uint) users ...

  5. Solidity教程系列1 - 类型介绍

    现在的Solidity中文文档,要么翻译的太烂,要么太旧,决定重新翻译下,再加上代码事例讲解. 写在前面 Solidity是以太坊智能合约编程语言,阅读本文前,你应该对以太坊.智能合约有所了解, 如果 ...

  6. 智能合约语言 Solidity 教程系列1 - 类型介绍

    现在的Solidity中文文档,要么翻译的太烂,要么太旧,决定重新翻译下.尤其点名批评极客学院名为<Solidity官方文档中文版>的翻译,机器翻译的都比它好,大家还是别看了. 写在前面 ...

  7. Dynamic Mapping和常见字段类型

    原文:Dynamic Mapping和常见字段类型 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn. ...

  8. [Contract] Solidity 变量类型的默认值

    变量的默认值一般都代表 “零值”. 比如 bool 就是 false,uint.int 就是 0,string 就是空字符串. 其它组合的参考 Solidity 判断 mapping 值的存在 Ref ...

  9. 以太坊智能合约 Solidity 的常用数据类型介绍

    目录 目录 1.数组 1.1.对数组的增删改查操作. 2.String.Bytes.Mapping的使用 3.Enums 和 Structs 的简单应用 4.Ether 单位和 Time 单位 5.A ...

随机推荐

  1. vc6中向vs2010迁移的几个问题

    vc6版本支持的库编译:CJ60lib 1. 用vs2010打开CJ60库的源码的dsw,强制打开 (1)设置项目属性的语言 因为,如果代码字符的编码集不一样,则会出现函数冲定义,参数冲突等问题,这可 ...

  2. Week Plan:强介入性的效率导师[转]

    做产品有三重境界,以效率工具这一细分领域为例: 第一重——发现用户需求,如 Fleep,敏锐地发现团队协作中的关键——聊天,围绕这一需求做足文章; 第二重——预见用户需求,如 ProcessOn,在以 ...

  3. mysql命令行客户端结果分页浏览

    转载请注明出处:http://xiezhenye.com/2008/06/mysql%e5%91%bd%e4%bb%a4%e8%a1%8c%e5%ae%a2%e6%88%b7%e7%ab%af%e7% ...

  4. 《jQuery基础教程(第四版)》学习笔记

    本书代码参考:Learning jQuery Code Listing Browser 原书: jQuery基础教程 目录: 第2章 选择元素 1. 使用$()函数 2. 选择符 3. DOM遍历方法 ...

  5. C#知识点提炼期末复习专用

    根据内部消息称:有三类题型:  程序阅读题:2题  简答题:2题 (主要是对概念的考查)  编程题:暂定2-3题 复习要点: .net framework 通用语言开发环境..NET基础类库..NET ...

  6. Python MySQL - 进行数据查询

    #coding=utf-8 import mysql.connector import importlib import sys # reload(sys) # sys.setdefaultencod ...

  7. Java按时间梯度实现异步回调接口

    1. 背景 在业务处理完之后,需要调用其他系统的接口,将相应的处理结果通知给对方,若是同步请求,假如调用的系统出现异常或是宕机等事件,会导致自身业务受到影响,事务会一直阻塞,数据库连接不够用等异常现象 ...

  8. java实现文件上传下载

    喜欢的朋友可以关注下,粉丝也缺. 今天发现已经有很久没有给大家分享一篇技术文章了,于是想了一下给大家分享一篇java实现文件上传下载功能的文章,不喜欢的希望大家勿喷. 想必大家都知道文件的上传前端页面 ...

  9. [Spring]IOC控制反转和DI依赖注入

    从之前算起到现在接触Spring也已经有几天了,进度也不是很快,就只弄懂了控制反转和依赖注入那么一点东西.然后敲了两个demo 主要是因为之前没有学过,然后网上资源很多但是都不是面向我们初学者的,大多 ...

  10. 善用Intellij插件可大幅提升我们的效率

    转自 :https://www.jianshu.com/p/686ba0ae4ac2 1. .ignore 生成各种ignore文件,一键创建git ignore文件的模板,免得自己去写 截图: 2. ...