Map / Dict / Hash Table
Abstractions
- Java
LinkedHashMap
= pythoncollections.OrderedDict
: remembers the order that keys were first inserted - Java
TreeMap
: red-black tree based, sorted by the keys, log(n) for all actions; no python equivalent
C++
Standard Library:
std::map
: Similar toabsl::btree_map
, provided by the standard but significantly less performant.std::unordered_map
: Similar toabsl::flat_hash_map
, provided by the standard but significantly less performant.
Abseil:
absl::flat_hash_map
: an unordered collection that maps each (unique) key to a not-necessarily-unique value;absl::node_hash_map
: Similar to absl::flat_hash_map, but uses separate allocations for the key and value, thus providing pointer stability;absl::btree_map
: an ordered collection that maps each (unique) key to a not-necessarily-unique value;
Rust
std::collections::HashMap
std::collections::BTreeMap
Java
HashMap
Python
dict
Go
map
JavaScript
object
Basics: Creat, Set, Get
C++
// map<char, int> m
m['a'] = 1;
Go
// create
m := make(map[string]int)
// get
v := m["Answer"]
v, ok := m["Answer"]
// set
m["Answer"] = 42
// delete
delete(m, "Answer")
Rust
let mut m = HashMap::new();
m.insert('a', 1);
Java
// create
Map<Character, Integer> m = new HashMap<>();
// set value
m.put('a', 1);
// get value
m.get('a');
JavaScript
// create
const a = {};
// set value
a['key'] = 'value';
// get value
a['key'];
// get or else:
// if 'key' is not in the object, return 0
a['key'] || 0;
Python
Normal dict
:
a = {}
a.get('key', 0)
defaultdict
: will "default" a value if that key has not been set yet.
>>> import collections
>>> d = collections.defaultdict(lambda: 1)
>>> d
defaultdict(<function <lambda> at 0x104c64f28>, {})
>>> d[1]
1
No default lambda provided will throw exception
>>> c = collections.defaultdict()
>>> c[1]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
KeyError: 1
Here lambda: 1
is the same as the parameterless function f that does this
def f():
return 1
Initialization
JavaScript
Object Spread Properties
var a = 1,
b = 2,
c = 3;
var x = { x: 4, y: 5, z: 6 };
var obj = { a, b, c, ...x };
console.log(obj); //{a: 1, b: 2, c: 3, x: 4, y: 5, z: 6};
Object Spread is "last one in wins"
> a = {b : 1, c: 2}
{b: 1, c: 2}
> x = {y : 3, z : 4, c: 5}
{y: 3, z: 4, c: 5}
> n = {...a, ...x}
{b: 1, c: 5, y: 3, z: 4}
Clone
JavaScript
let clone = Object.assign({}, obj);
Contains Key
JavaScript
in
operator matches all object keys, including those in the object's prototype chain.
if ('key' in obj) {
// ...
}
.hasOwnProperty('key')
checks any object's own keys:
obj.hasOwnProperty('key');
Go
Use a two-value assignment:
if item, ok := m[key]; ok {
// ...
}
Contains Value
JavaScript
Object.values(obj).includes('foo');
Count Elements
Get Keys
Go
Use for k := range m
to get keys; the iteration order is not specified, to get sorted keys:
m := make(map[int]int)
var keys []int
for k := range m {
keys = append(keys, k)
}
sort.Ints(keys)
for _, k := range keys {
// ...
}
Python
Get keys of a dict
:
d.keys()
JavaScript
Object.keys(obj);
Java
Map<Integer, String> map = new HashMap<>();
List<Integer> result = map.entrySet().stream()
.map(x -> x.getKey())
.collect(Collectors.toList());
Get Values
Iteration
JavaScript
Use Object.keys(obj)
, Object.values(obj)
and Object.entries(obj)
, e.g.
for (const [key, value] of Object.entries(obj)) {
// ...
}
Use for ... in ...
:
for (const key in object) {
console.log(`${key}: ${object[key]}`);
}
Destructuring
JavaScript
const { children, location } = this.props;
Object Rest Properties
var { a, b, c, ...x } = { a: 1, b: 2, c: 3, x: 4, y: 5, z: 6 };
console.log(a); // 1
console.log(b); // 2
console.log(c); // 3
console.log(x); // { x: 4, y: 5, z: 6 }