Mapping Iterable
WEB3DEV Team
# Mapping Iterable
No puedes iterar a través de un mapping
. Aquí hay un ejemplo de cómo crear un mapping
iterable.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.3;
library IterableMapping {
// Mapping iterable desde address a uint;
struct Map {
address[] keys;
mapping(address => uint) values;
mapping(address => uint) indexOf;
mapping(address => bool) inserted;
}
function get(Map storage map, address key) public view returns (uint) {
return map.values[key];
}
function getKeyAtIndex(Map storage map, uint index) public view returns (address) {
return map.keys[index];
}
function size(Map storage map) public view returns (uint) {
return map.keys.length;
}
function set(
Map storage map,
address key,
uint val
) public {
if (map.inserted[key]) {
map.values[key] = val;
} else {
map.inserted[key] = true;
map.values[key] = val;
map.indexOf[key] = map.keys.length;
map.keys.push(key);
}
}
function remove(Map storage map, address key) public {
if (!map.inserted[key]) {
return;
}
delete map.inserted[key];
delete map.values[key];
uint index = map.indexOf[key];
uint lastIndex = map.keys.length - 1;
address lastKey = map.keys[lastIndex];
map.indexOf[lastKey] = index;
delete map.indexOf[key];
map.keys[index] = lastKey;
map.keys.pop();
}
}
contract TestIterableMap {
using IterableMapping for IterableMapping.Map;
IterableMapping.Map private map;
function testIterableMap() public {
map.set(address(0), 0);
map.set(address(1), 100);
map.set(address(2), 200); // inserta
map.set(address(2), 200); // actualiza
map.set(address(3), 300);
for (uint i = 0; i < map.size(); i++) {
address key = map.getKeyAtIndex(i);
assert(map.get(key) == i * 100);
}
map.remove(address(1));
// keys = [address(0), address(3), address(2)]
assert(map.size() == 3);
assert(map.getKeyAtIndex(0) == address(0));
assert(map.getKeyAtIndex(1) == address(3));
assert(map.getKeyAtIndex(2) == address(2));
}
}