阅读(1491)
赞(11)
可迭代映射
2022-05-12 09:58:17 更新
你不能迭代映射,即你不能枚举它们的键。但是,可以在它们之上实现一个数据结构并对其进行迭代。例如,下面的代码实现了一个 IterableMapping库,User然后合约将数据添加到该库中,并且该sum函数迭代以对所有值求和。
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.8; struct IndexValue { uint keyIndex; uint value; } struct KeyFlag { uint key; bool deleted; } struct itmap { mapping(uint => IndexValue) data; KeyFlag[] keys; uint size; } type Iterator is uint; library IterableMapping { function insert(itmap storage self, uint key, uint value) internal 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.keys.push(); self.data[key].keyIndex = keyIndex + 1; self.keys[keyIndex].key = key; self.size++; return false; } } function remove(itmap storage self, uint key) internal 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) internal view returns (bool) { return self.data[key].keyIndex > 0; } function iterateStart(itmap storage self) internal view returns (Iterator) { return iteratorSkipDeleted(self, 0); } function iterateValid(itmap storage self, Iterator iterator) internal view returns (bool) { return Iterator.unwrap(iterator) < self.keys.length; } function iterateNext(itmap storage self, Iterator iterator) internal view returns (Iterator) { return iteratorSkipDeleted(self, Iterator.unwrap(iterator) + 1); } function iterateGet(itmap storage self, Iterator iterator) internal view returns (uint key, uint value) { uint keyIndex = Iterator.unwrap(iterator); key = self.keys[keyIndex].key; value = self.data[key].value; } function iteratorSkipDeleted(itmap storage self, uint keyIndex) private view returns (Iterator) { while (keyIndex < self.keys.length && self.keys[keyIndex].deleted) keyIndex++; return Iterator.wrap(keyIndex); } } // How to use it contract User { // Just a struct holding our data. itmap data; // Apply library functions to the data type. using IterableMapping for itmap; // Insert something function insert(uint k, uint v) public returns (uint size) { // This calls IterableMapping.insert(data, k, v) data.insert(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() public view returns (uint s) { for ( Iterator i = data.iterateStart(); data.iterateValid(i); i = data.iterateNext(i) ) { (, uint value) = data.iterateGet(i); s += value; } } }
← 结构体