ordered_map - [mainnet]
This module provides an implementation for an ordered map.
Keys point to values, and each key in the map must be unique.
Currently, one implementation is provided, backed by a single sorted vector.
That means that keys can be found within O(log N) time. Adds and removals take O(N) time, but the constant factor is small, as it does only O(log N) comparisons, and does efficient mem-copy with vector operations.
Additionally, it provides a way to lookup and iterate over sorted keys, making range query take O(log N + R) time (where R is number of elements in the range).
Most methods operate with OrderedMap being self
.
All methods that start with iter_*, operate with IteratorPtr being self
.
Uses cmp::compare for ordering, which compares primitive types natively, and uses common lexicographical sorting for complex types.
TODO: all iterator functions are public(friend) for now, so that they can be modified in a backward incompatible way. Type is also named IteratorPtr, so that Iterator is free to use later. They are waiting for Move improvement that will allow references to be part of the struct, allowing cleaner iterator APIs.
use 0x1::cmp;use 0x1::error;use 0x1::option;use 0x1::vector;
Constants
const EITER_OUT_OF_BOUNDS: u64 = 3;
Map key already exists
const EKEY_ALREADY_EXISTS: u64 = 1;
Map key is not found
const EKEY_NOT_FOUND: u64 = 2;
New key used in replace_key_inplace doesn’t respect the order
const ENEW_KEY_NOT_IN_ORDER: u64 = 4;
Structs
Entry
Individual entry holding (key, value) pair
struct Entry<K, V> has copy, drop, store
Fields
-
key: K
-
value: V
Functions
new
Create a new empty OrderedMap, using default (SortedVectorMap) implementation.
public fun new<K, V>(): ordered_map::OrderedMap<K, V>
Implementation
public fun new<K, V>(): OrderedMap<K, V> { OrderedMap::SortedVectorMap { entries: vector::empty(), }}
new_from
Create a OrderedMap from a vector of keys and values. Aborts with EKEY_ALREADY_EXISTS if duplicate keys are passed in.
public fun new_from<K, V>(keys: vector<K>, values: vector<V>): ordered_map::OrderedMap<K, V>
Implementation
public fun new_from<K, V>(keys: vector<K>, values: vector<V>): OrderedMap<K, V> { let map = new(); map.add_all(keys, values); map}
length
Number of elements in the map.
public fun length<K, V>(self: &ordered_map::OrderedMap<K, V>): u64
Implementation
public fun length<K, V>(self: &OrderedMap<K, V>): u64 { self.entries.length()}
is_empty
Whether map is empty.
public fun is_empty<K, V>(self: &ordered_map::OrderedMap<K, V>): bool
Implementation
public fun is_empty<K, V>(self: &OrderedMap<K, V>): bool { self.entries.is_empty()}
add
Add a key/value pair to the map. Aborts with EKEY_ALREADY_EXISTS if key already exist.
public fun add<K, V>(self: &mut ordered_map::OrderedMap<K, V>, key: K, value: V)
Implementation
public fun add<K, V>(self: &mut OrderedMap<K, V>, key: K, value: V) { let len = self.entries.length(); let index = binary_search(&key, &self.entries, 0, len);
// key must not already be inside. assert!(index >= len || &self.entries[index].key != &key, error::invalid_argument(EKEY_ALREADY_EXISTS)); self.entries.insert(index, Entry { key, value });}
upsert
If the key doesn’t exist in the map, inserts the key/value, and returns none. Otherwise, updates the value under the given key, and returns the old value.
public fun upsert<K: drop, V>(self: &mut ordered_map::OrderedMap<K, V>, key: K, value: V): option::Option<V>
Implementation
public fun upsert<K: drop, V>(self: &mut OrderedMap<K, V>, key: K, value: V): Option<V> { let len = self.entries.length(); let index = binary_search(&key, &self.entries, 0, len);
if (index < len && &self.entries[index].key == &key) { let Entry { key: _, value: old_value, } = self.entries.replace(index, Entry { key, value }); option::some(old_value) } else { self.entries.insert(index, Entry { key, value }); option::none() }}
remove
Remove a key/value pair from the map.
Aborts with EKEY_NOT_FOUND if key
doesn’t exist.
public fun remove<K: drop, V>(self: &mut ordered_map::OrderedMap<K, V>, key: &K): V
Implementation
public fun remove<K: drop, V>(self: &mut OrderedMap<K, V>, key: &K): V { let len = self.entries.length(); let index = binary_search(key, &self.entries, 0, len); assert!(index < len, error::invalid_argument(EKEY_NOT_FOUND)); let Entry { key: old_key, value } = self.entries.remove(index); assert!(key == &old_key, error::invalid_argument(EKEY_NOT_FOUND)); value}
contains
Returns whether map contains a given key.
public fun contains<K, V>(self: &ordered_map::OrderedMap<K, V>, key: &K): bool
Implementation
public fun contains<K, V>(self: &OrderedMap<K, V>, key: &K): bool { !self.find(key).iter_is_end(self)}
borrow
public fun borrow<K, V>(self: &ordered_map::OrderedMap<K, V>, key: &K): &V
Implementation
public fun borrow<K, V>(self: &OrderedMap<K, V>, key: &K): &V { self.find(key).iter_borrow(self)}
borrow_mut
public fun borrow_mut<K, V>(self: &mut ordered_map::OrderedMap<K, V>, key: &K): &mut V
Implementation
public fun borrow_mut<K, V>(self: &mut OrderedMap<K, V>, key: &K): &mut V { self.find(key).iter_borrow_mut(self)}
replace_key_inplace
Changes the key, while keeping the same value attached to it
Aborts with EKEY_NOT_FOUND if old_key
doesn’t exist.
Aborts with ENEW_KEY_NOT_IN_ORDER if new_key
doesn’t keep the order old_key
was in.
public(friend) fun replace_key_inplace<K: drop, V>(self: &mut ordered_map::OrderedMap<K, V>, old_key: &K, new_key: K)
Implementation
public(friend) fun replace_key_inplace<K: drop, V>(self: &mut OrderedMap<K, V>, old_key: &K, new_key: K) { let len = self.entries.length(); let index = binary_search(old_key, &self.entries, 0, len); assert!(index < len, error::invalid_argument(EKEY_NOT_FOUND));
assert!(old_key == &self.entries[index].key, error::invalid_argument(EKEY_NOT_FOUND));
// check that after we update the key, order is going to be respected if (index > 0) { assert!(cmp::compare(&self.entries[index - 1].key, &new_key).is_lt(), error::invalid_argument(ENEW_KEY_NOT_IN_ORDER)) };
if (index + 1 < len) { assert!(cmp::compare(&new_key, &self.entries[index + 1].key).is_lt(), error::invalid_argument(ENEW_KEY_NOT_IN_ORDER)) };
self.entries[index].key = new_key;}
add_all
Add multiple key/value pairs to the map. The keys must not already exist. Aborts with EKEY_ALREADY_EXISTS if key already exist, or duplicate keys are passed in.
public fun add_all<K, V>(self: &mut ordered_map::OrderedMap<K, V>, keys: vector<K>, values: vector<V>)
Implementation
public fun add_all<K, V>(self: &mut OrderedMap<K, V>, keys: vector<K>, values: vector<V>) { // TODO: Can be optimized, by sorting keys and values, and then creating map. keys.zip(values, |key, value| { self.add(key, value); });}
upsert_all
Add multiple key/value pairs to the map, overwrites values if they exist already, or if duplicate keys are passed in.
public fun upsert_all<K: drop, V: drop>(self: &mut ordered_map::OrderedMap<K, V>, keys: vector<K>, values: vector<V>)
Implementation
public fun upsert_all<K: drop, V: drop>(self: &mut OrderedMap<K, V>, keys: vector<K>, values: vector<V>) { // TODO: Can be optimized, by sorting keys and values, and then creating map. keys.zip(values, |key, value| { self.upsert(key, value); });}
append
Takes all elements from other
and adds them to self
,
overwritting if any key is already present in self.
public fun append<K: drop, V: drop>(self: &mut ordered_map::OrderedMap<K, V>, other: ordered_map::OrderedMap<K, V>)
Implementation
public fun append<K: drop, V: drop>(self: &mut OrderedMap<K, V>, other: OrderedMap<K, V>) { self.append_impl(other);}
append_disjoint
Takes all elements from other
and adds them to self
.
Aborts with EKEY_ALREADY_EXISTS if other
has a key already present in self
.
public fun append_disjoint<K, V>(self: &mut ordered_map::OrderedMap<K, V>, other: ordered_map::OrderedMap<K, V>)
Implementation
public fun append_disjoint<K, V>(self: &mut OrderedMap<K, V>, other: OrderedMap<K, V>) { let overwritten = self.append_impl(other); assert!(overwritten.length() == 0, error::invalid_argument(EKEY_ALREADY_EXISTS)); overwritten.destroy_empty();}
append_impl
Takes all elements from other
and adds them to self
, returning list of entries in self that were overwritten.
fun append_impl<K, V>(self: &mut ordered_map::OrderedMap<K, V>, other: ordered_map::OrderedMap<K, V>): vector<ordered_map::Entry<K, V>>
Implementation
fun append_impl<K, V>(self: &mut OrderedMap<K, V>, other: OrderedMap<K, V>): vector<Entry<K,V>> { let OrderedMap::SortedVectorMap { entries: other_entries, } = other; let overwritten = vector::empty();
if (other_entries.is_empty()) { other_entries.destroy_empty(); return overwritten; };
if (self.entries.is_empty()) { self.entries.append(other_entries); return overwritten; };
// Optimization: if all elements in `other` are larger than all elements in `self`, we can just move them over. if (cmp::compare(&self.entries.borrow(self.entries.length() - 1).key, &other_entries.borrow(0).key).is_lt()) { self.entries.append(other_entries); return overwritten; };
// In O(n), traversing from the back, build reverse sorted result, and then reverse it back let reverse_result = vector::empty(); let cur_i = self.entries.length() - 1; let other_i = other_entries.length() - 1;
// after the end of the loop, other_entries is empty, and any leftover is in entries loop { let ord = cmp::compare(&self.entries[cur_i].key, &other_entries[other_i].key); if (ord.is_gt()) { reverse_result.push_back(self.entries.pop_back()); if (cur_i == 0) { // make other_entries empty, and rest in entries. // TODO cannot use mem::swap until it is public/released // mem::swap(&mut self.entries, &mut other_entries); self.entries.append(other_entries); break; } else { cur_i -= 1; }; } else { // is_lt or is_eq if (ord.is_eq()) { // we skip the entries one, and below put in the result one from other. overwritten.push_back(self.entries.pop_back()); };
reverse_result.push_back(other_entries.pop_back()); if (other_i == 0) { other_entries.destroy_empty(); break; } else { other_i -= 1; }; }; };
self.entries.reverse_append(reverse_result);
overwritten}
trim
Splits the collection into two, such to leave self
with at
number of elements.
Returns a newly allocated map containing the elements in the range [at, len).
After the call, the original map will be left containing the elements [0, at).
public fun trim<K, V>(self: &mut ordered_map::OrderedMap<K, V>, at: u64): ordered_map::OrderedMap<K, V>
Implementation
public fun trim<K, V>(self: &mut OrderedMap<K, V>, at: u64): OrderedMap<K, V> { let rest = self.entries.trim(at);
OrderedMap::SortedVectorMap { entries: rest }}
borrow_front
public fun borrow_front<K, V>(self: &ordered_map::OrderedMap<K, V>): (&K, &V)
Implementation
public fun borrow_front<K, V>(self: &OrderedMap<K, V>): (&K, &V) { let entry = self.entries.borrow(0); (&entry.key, &entry.value)}
borrow_back
public fun borrow_back<K, V>(self: &ordered_map::OrderedMap<K, V>): (&K, &V)
Implementation
public fun borrow_back<K, V>(self: &OrderedMap<K, V>): (&K, &V) { let entry = self.entries.borrow(self.entries.length() - 1); (&entry.key, &entry.value)}
pop_front
public fun pop_front<K, V>(self: &mut ordered_map::OrderedMap<K, V>): (K, V)
Implementation
public fun pop_front<K, V>(self: &mut OrderedMap<K, V>): (K, V) { let Entry { key, value } = self.entries.remove(0); (key, value)}
pop_back
public fun pop_back<K, V>(self: &mut ordered_map::OrderedMap<K, V>): (K, V)
Implementation
public fun pop_back<K, V>(self: &mut OrderedMap<K, V>): (K, V) { let Entry { key, value } = self.entries.pop_back(); (key, value)}
prev_key
public fun prev_key<K: copy, V>(self: &ordered_map::OrderedMap<K, V>, key: &K): option::Option<K>
Implementation
public fun prev_key<K: copy, V>(self: &OrderedMap<K, V>, key: &K): Option<K> { let it = self.lower_bound(key); if (it.iter_is_begin(self)) { option::none() } else { option::some(*it.iter_prev(self).iter_borrow_key(self)) }}
next_key
public fun next_key<K: copy, V>(self: &ordered_map::OrderedMap<K, V>, key: &K): option::Option<K>
Implementation
public fun next_key<K: copy, V>(self: &OrderedMap<K, V>, key: &K): Option<K> { let it = self.lower_bound(key); if (it.iter_is_end(self)) { option::none() } else { let cur_key = it.iter_borrow_key(self); if (key == cur_key) { let it = it.iter_next(self); if (it.iter_is_end(self)) { option::none() } else { option::some(*it.iter_borrow_key(self)) } } else { option::some(*cur_key) } }}
lower_bound
Returns an iterator pointing to the first element that is greater or equal to the provided key, or an end iterator if such element doesn’t exist.
public(friend) fun lower_bound<K, V>(self: &ordered_map::OrderedMap<K, V>, key: &K): ordered_map::IteratorPtr
Implementation
public(friend) fun lower_bound<K, V>(self: &OrderedMap<K, V>, key: &K): IteratorPtr { let entries = &self.entries; let len = entries.length();
let index = binary_search(key, entries, 0, len); if (index == len) { self.new_end_iter() } else { new_iter(index) }}
find
Returns an iterator pointing to the element that equals to the provided key, or an end iterator if the key is not found.
public(friend) fun find<K, V>(self: &ordered_map::OrderedMap<K, V>, key: &K): ordered_map::IteratorPtr
Implementation
public(friend) fun find<K, V>(self: &OrderedMap<K, V>, key: &K): IteratorPtr { let lower_bound = self.lower_bound(key); if (lower_bound.iter_is_end(self)) { lower_bound } else if (lower_bound.iter_borrow_key(self) == key) { lower_bound } else { self.new_end_iter() }}
new_begin_iter
Returns the begin iterator.
public(friend) fun new_begin_iter<K, V>(self: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
Implementation
public(friend) fun new_begin_iter<K, V>(self: &OrderedMap<K, V>): IteratorPtr { if (self.is_empty()) { return IteratorPtr::End; };
new_iter(0)}
new_end_iter
Returns the end iterator.
public(friend) fun new_end_iter<K, V>(self: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
Implementation
public(friend) fun new_end_iter<K, V>(self: &OrderedMap<K, V>): IteratorPtr { IteratorPtr::End}
iter_next
Returns the next iterator, or none if already at the end iterator. Note: Requires that the map is not changed after the input iterator is generated.
public(friend) fun iter_next<K, V>(self: ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
Implementation
public(friend) fun iter_next<K, V>(self: IteratorPtr, map: &OrderedMap<K, V>): IteratorPtr { assert!(!self.iter_is_end(map), error::invalid_argument(EITER_OUT_OF_BOUNDS));
let index = self.index + 1; if (index < map.entries.length()) { new_iter(index) } else { map.new_end_iter() }}
iter_prev
Returns the previous iterator, or none if already at the begin iterator. Note: Requires that the map is not changed after the input iterator is generated.
public(friend) fun iter_prev<K, V>(self: ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): ordered_map::IteratorPtr
Implementation
public(friend) fun iter_prev<K, V>(self: IteratorPtr, map: &OrderedMap<K, V>): IteratorPtr { assert!(!self.iter_is_begin(map), error::invalid_argument(EITER_OUT_OF_BOUNDS));
let index = if (self is IteratorPtr::End) { map.entries.length() - 1 } else { self.index - 1 };
new_iter(index)}
iter_is_begin
Returns whether the iterator is a begin iterator.
public(friend) fun iter_is_begin<K, V>(self: &ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): bool
Implementation
public(friend) fun iter_is_begin<K, V>(self: &IteratorPtr, map: &OrderedMap<K, V>): bool { if (self is IteratorPtr::End) { map.is_empty() } else { self.index == 0 }}
iter_is_begin_from_non_empty
Returns true iff the iterator is a begin iterator from a non-empty collection. (I.e. if iterator points to a valid element) This method doesn’t require having access to map, unlike iter_is_begin.
public(friend) fun iter_is_begin_from_non_empty(self: &ordered_map::IteratorPtr): bool
Implementation
public(friend) fun iter_is_begin_from_non_empty(self: &IteratorPtr): bool { if (self is IteratorPtr::End) { false } else { self.index == 0 }}
iter_is_end
Returns whether the iterator is an end iterator.
public(friend) fun iter_is_end<K, V>(self: &ordered_map::IteratorPtr, _map: &ordered_map::OrderedMap<K, V>): bool
Implementation
public(friend) fun iter_is_end<K, V>(self: &IteratorPtr, _map: &OrderedMap<K, V>): bool { self is IteratorPtr::End}
iter_borrow_key
Borrows the key given iterator points to. Aborts with EITER_OUT_OF_BOUNDS if iterator is pointing to the end. Note: Requires that the map is not changed after the input iterator is generated.
public(friend) fun iter_borrow_key<K, V>(self: &ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): &K
Implementation
public(friend) fun iter_borrow_key<K, V>(self: &IteratorPtr, map: &OrderedMap<K, V>): &K { assert!(!(self is IteratorPtr::End), error::invalid_argument(EITER_OUT_OF_BOUNDS));
&map.entries.borrow(self.index).key}
iter_borrow
Borrows the value given iterator points to. Aborts with EITER_OUT_OF_BOUNDS if iterator is pointing to the end. Note: Requires that the map is not changed after the input iterator is generated.
public(friend) fun iter_borrow<K, V>(self: ordered_map::IteratorPtr, map: &ordered_map::OrderedMap<K, V>): &V
Implementation
public(friend) fun iter_borrow<K, V>(self: IteratorPtr, map: &OrderedMap<K, V>): &V { assert!(!(self is IteratorPtr::End), error::invalid_argument(EITER_OUT_OF_BOUNDS)); &map.entries.borrow(self.index).value}
iter_borrow_mut
Mutably borrows the value iterator points to. Aborts with EITER_OUT_OF_BOUNDS if iterator is pointing to the end. Note: Requires that the map is not changed after the input iterator is generated.
public(friend) fun iter_borrow_mut<K, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>): &mut V
Implementation
public(friend) fun iter_borrow_mut<K, V>(self: IteratorPtr, map: &mut OrderedMap<K, V>): &mut V { assert!(!(self is IteratorPtr::End), error::invalid_argument(EITER_OUT_OF_BOUNDS)); &mut map.entries.borrow_mut(self.index).value}
iter_remove
Removes (key, value) pair iterator points to, returning the previous value. Aborts with EITER_OUT_OF_BOUNDS if iterator is pointing to the end. Note: Requires that the map is not changed after the input iterator is generated.
public(friend) fun iter_remove<K: drop, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>): V
Implementation
public(friend) fun iter_remove<K: drop, V>(self: IteratorPtr, map: &mut OrderedMap<K, V>): V { assert!(!(self is IteratorPtr::End), error::invalid_argument(EITER_OUT_OF_BOUNDS));
let Entry { key: _, value } = map.entries.remove(self.index); value}
iter_replace
Replaces the value iterator is pointing to, returning the previous value. Aborts with EITER_OUT_OF_BOUNDS if iterator is pointing to the end. Note: Requires that the map is not changed after the input iterator is generated.
public(friend) fun iter_replace<K: copy, drop, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>, value: V): V
Implementation
public(friend) fun iter_replace<K: copy + drop, V>(self: IteratorPtr, map: &mut OrderedMap<K, V>, value: V): V { assert!(!(self is IteratorPtr::End), error::invalid_argument(EITER_OUT_OF_BOUNDS));
// TODO once mem::replace is public/released, update to: // let entry = map.entries.borrow_mut(self.index); // mem::replace(&mut entry.value, value) let key = map.entries[self.index].key; let Entry { key: _, value: prev_value, } = map.entries.replace(self.index, Entry { key, value }); prev_value}
iter_add
Add key/value pair to the map, at the iterator position (before the element at the iterator position). Aborts with ENEW_KEY_NOT_IN_ORDER is key is not larger than the key before the iterator, or smaller than the key at the iterator position.
public(friend) fun iter_add<K, V>(self: ordered_map::IteratorPtr, map: &mut ordered_map::OrderedMap<K, V>, key: K, value: V)
Implementation
public(friend) fun iter_add<K, V>(self: IteratorPtr, map: &mut OrderedMap<K, V>, key: K, value: V) { let len = map.entries.length(); let insert_index = if (self is IteratorPtr::End) { len } else { self.index };
if (insert_index > 0) { assert!(cmp::compare(&map.entries[insert_index - 1].key, &key).is_lt(), error::invalid_argument(ENEW_KEY_NOT_IN_ORDER)) };
if (insert_index < len) { assert!(cmp::compare(&key, &map.entries[insert_index].key).is_lt(), error::invalid_argument(ENEW_KEY_NOT_IN_ORDER)) };
map.entries.insert(insert_index, Entry { key, value });}
destroy_empty
Destroys empty map.
Aborts if self
is not empty.
public fun destroy_empty<K, V>(self: ordered_map::OrderedMap<K, V>)
Implementation
public fun destroy_empty<K, V>(self: OrderedMap<K, V>) { let OrderedMap::SortedVectorMap { entries } = self; // assert!(entries.is_empty(), E_NOT_EMPTY); entries.destroy_empty();}
keys
Return all keys in the map. This requires keys to be copyable.
public fun keys<K: copy, V>(self: &ordered_map::OrderedMap<K, V>): vector<K>
Implementation
public fun keys<K: copy, V>(self: &OrderedMap<K, V>): vector<K> { self.entries.map_ref(|e| { let e: &Entry<K, V> = e; e.key })}
values
Return all values in the map. This requires values to be copyable.
public fun values<K, V: copy>(self: &ordered_map::OrderedMap<K, V>): vector<V>
Implementation
public fun values<K, V: copy>(self: &OrderedMap<K, V>): vector<V> { self.entries.map_ref(|e| { let e: &Entry<K, V> = e; e.value })}
to_vec_pair
Transform the map into two vectors with the keys and values respectively Primarily used to destroy a map
public fun to_vec_pair<K, V>(self: ordered_map::OrderedMap<K, V>): (vector<K>, vector<V>)
Implementation
public fun to_vec_pair<K, V>(self: OrderedMap<K, V>): (vector<K>, vector<V>) { let keys: vector<K> = vector::empty(); let values: vector<V> = vector::empty(); let OrderedMap::SortedVectorMap { entries } = self; entries.for_each(|e| { let Entry { key, value } = e; keys.push_back(key); values.push_back(value); }); (keys, values)}
destroy
For maps that cannot be dropped this is a utility to destroy them using lambdas to destroy the individual keys and values.
public fun destroy<K, V>(self: ordered_map::OrderedMap<K, V>, dk: |K|, dv: |V|)
Implementation
public inline fun destroy<K, V>( self: OrderedMap<K, V>, dk: |K|, dv: |V|) { let (keys, values) = self.to_vec_pair(); keys.destroy(|_k| dk(_k)); values.destroy(|_v| dv(_v));}
for_each
Apply the function to each key-value pair in the map, consuming it.
public fun for_each<K, V>(self: ordered_map::OrderedMap<K, V>, f: |(K, V)|)
Implementation
public inline fun for_each<K, V>( self: OrderedMap<K, V>, f: |K, V|) { let (keys, values) = self.to_vec_pair(); keys.zip(values, |k, v| f(k, v));}
for_each_ref
Apply the function to a reference of each key-value pair in the map.
Current implementation is O(n * log(n)). After function values will be optimized to O(n).
public fun for_each_ref<K: copy, drop, V>(self: &ordered_map::OrderedMap<K, V>, f: |(&K, &V)|)
Implementation
public inline fun for_each_ref<K: copy + drop, V>(self: &OrderedMap<K, V>, f: |&K, &V|) { // This implementation is innefficient: O(log(n)) for next_key / borrow lookups every time, // but is the only one available through the public API. if (!self.is_empty()) { let (k, v) = self.borrow_front(); f(k, v);
let cur_k = self.next_key(k); while (cur_k.is_some()) { let k = cur_k.destroy_some(); f(&k, self.borrow(&k));
cur_k = self.next_key(&k); }; };
// TODO: if we make iterator api public update to: // let iter = self.new_begin_iter(); // while (!iter.iter_is_end(self)) { // f(iter.iter_borrow_key(self), iter.iter_borrow(self)); // iter = iter.iter_next(self); // }
// TODO: once move supports private functions udpate to: // vector::for_each_ref( // &self.entries, // |entry| { // f(&entry.key, &entry.value) // } // );}
for_each_ref_friend
public(friend) fun for_each_ref_friend<K: copy, drop, V>(self: &ordered_map::OrderedMap<K, V>, f: |(&K, &V)|)
Implementation
public(friend) inline fun for_each_ref_friend<K: copy + drop, V>(self: &OrderedMap<K, V>, f: |&K, &V|) { let iter = self.new_begin_iter(); while (!iter.iter_is_end(self)) { f(iter.iter_borrow_key(self), iter.iter_borrow(self)); iter = iter.iter_next(self); }}
for_each_mut
Apply the function to a mutable reference of each key-value pair in the map.
Current implementation is O(n * log(n)). After function values will be optimized to O(n).
public fun for_each_mut<K: copy, drop, V>(self: &mut ordered_map::OrderedMap<K, V>, f: |(&K, &mut V)|)
Implementation
public inline fun for_each_mut<K: copy + drop, V>(self: &mut OrderedMap<K, V>, f: |&K, &mut V|) { // This implementation is innefficient: O(log(n)) for next_key / borrow lookups every time, // but is the only one available through the public API. if (!self.is_empty()) { let (k, _v) = self.borrow_front();
let k = *k; let done = false; while (!done) { f(&k, self.borrow_mut(&k));
let cur_k = self.next_key(&k); if (cur_k.is_some()) { k = cur_k.destroy_some(); } else { done = true; } }; };
// TODO: if we make iterator api public update to: // let iter = self.new_begin_iter(); // while (!iter.iter_is_end(self)) { // let key = *iter.iter_borrow_key(self); // f(key, iter.iter_borrow_mut(self)); // iter = iter.iter_next(self); // }
// TODO: once move supports private functions udpate to: // vector::for_each_mut( // &mut self.entries, // |entry| { // f(&mut entry.key, &mut entry.value) // } // );}
new_iter
fun new_iter(index: u64): ordered_map::IteratorPtr
Implementation
inline fun new_iter(index: u64): IteratorPtr { IteratorPtr::Position { index: index, }}
binary_search
fun binary_search<K, V>(key: &K, entries: &vector<ordered_map::Entry<K, V>>, start: u64, end: u64): u64
Implementation
fun binary_search<K, V>(key: &K, entries: &vector<Entry<K, V>>, start: u64, end: u64): u64 { let l = start; let r = end; while (l != r) { let mid = l + ((r - l) >> 1); let comparison = cmp::compare(&entries.borrow(mid).key, key); if (comparison.is_lt()) { l = mid + 1; } else { r = mid; }; }; l}
Specification
pragma verify = false;
Enum OrderedMap
The OrderedMap datastructure.
enum OrderedMap<K, V> has copy, drop, store
Variants
SortedVectorMap
Fields
-
entries: vector<ordered_map::Entry<K, V>>
- List of entries, sorted by key.
Enum IteratorPtr
An iterator pointing to a valid position in an ordered map, or to the end.
TODO: Once fields can be (mutable) references, this class will be deprecated.
enum IteratorPtr has copy, drop
Variants
End
Fields
Position
Fields
-
index: u64
- The index of the iterator pointing to.