mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add updated iterable mapping example
Remove unused var
This commit is contained in:
parent
9bec533453
commit
1a88bc97df
@ -53,7 +53,100 @@ each ``_KeyType``, recursively. For example with a mapping:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.. index:: !iterable mappings
|
||||||
|
.. _iterable-mappings:
|
||||||
|
|
||||||
.. note::
|
Iterable Mappings
|
||||||
Mappings are not iterable, but it is possible to implement a data structure
|
-----------------
|
||||||
on top of them. For an example, see `iterable mapping <https://github.com/ethereum/dapp-bin/blob/master/library/iterable_mapping.sol>`_.
|
|
||||||
|
Mappings are not iterable, but it is possible to implement a data structure on
|
||||||
|
top of them and iterate over that. For example, the code below implements an
|
||||||
|
``IterableMapping`` library that the ``User`` contract then adds data too, and
|
||||||
|
the ``sum`` function iterates over to sum all the values.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
pragma solidity >=0.4.0 <0.7.0;
|
||||||
|
|
||||||
|
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) 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.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 iterate_start(itmap storage self) internal view returns (uint keyIndex) {
|
||||||
|
return iterate_next(self, uint(-1));
|
||||||
|
}
|
||||||
|
|
||||||
|
function iterate_valid(itmap storage self, uint keyIndex) internal view returns (bool) {
|
||||||
|
return keyIndex < self.keys.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
function iterate_next(itmap storage self, uint keyIndex) internal view 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) internal view returns (uint key, uint value) {
|
||||||
|
key = self.keys[keyIndex].key;
|
||||||
|
value = self.data[key].value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// How to use it
|
||||||
|
contract User {
|
||||||
|
// Just a struct holding our data.
|
||||||
|
IterableMapping.itmap data;
|
||||||
|
|
||||||
|
// Insert something
|
||||||
|
function insert(uint k, uint v) public 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() public view returns (uint s) {
|
||||||
|
for (uint i = IterableMapping.iterate_start(data);
|
||||||
|
IterableMapping.iterate_valid(data, i);
|
||||||
|
i = IterableMapping.iterate_next(data, i)) {
|
||||||
|
(, uint value) = IterableMapping.iterate_get(data, i);
|
||||||
|
s += value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user