dictionary - Does Dart have something like `defaultdict` in Python? - TagMerge
4Does Dart have something like `defaultdict` in Python?Does Dart have something like `defaultdict` in Python?

Does Dart have something like `defaultdict` in Python?

Asked 1 years ago
5
4 answers

You can use the putIfAbsent method on Map to create and insert e.g. an empty list to the map if it does not already exists: https://api.dart.dev/stable/2.7.2/dart-core/Map/putIfAbsent.html

void main() {
  Map<String, List<int>> m = {};

  m.putIfAbsent('001', () => []).add(1);
  m.putIfAbsent('001', () => []).add(2);
  m.putIfAbsent('002', () => []).add(3);

  print(m); // {001: [1, 2], 002: [3]}
}

Alternative solution

If you are going to use this pattern a lot it can be easier to just implement your own Defaultdict class which is not that complicated since we just want it to behave like a Map:

import 'dart:collection';

class Defaultdict<K, V> extends MapBase<K, V> {
  final Map<K, V> _map = {};
  final V Function() _ifAbsent;

  Defaultdict(this._ifAbsent);

  @override
  V operator [](Object? key) => _map.putIfAbsent(key as K, _ifAbsent);

  @override
  void operator []=(K key, V value) => _map[key] = value;

  @override
  void clear() => _map.clear();

  @override
  Iterable<K> get keys => _map.keys;

  @override
  V? remove(Object? key) => _map.remove(key);
}

void main() {
  // Create a Defaultdict where we return a empty new list for unknown keys
  final m = Defaultdict<String, List<int>>(() => []);

  m['001'].add(1);
  m['001'].add(2);
  m['002'].add(3);

  print(m); // {001: [1, 2], 002: [3]}
}

Source: link

2

I usually use ??= when possible:

var m = <String, List<DataObject>>{};
(m['001'] ??= []).add(DataObject(something: something));
(m['002'] ??= []).add(DataObject(something: something));

Note that this isn't quite the same as using putIfAbsent since it will overwrite entries where the key exists but the value is null. If you never store null in your Map, then use whichever you think is cleaner.

Source: link

0

>>>
>>> a_dict = {}
>>> a_dict['missing_key']
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
    a_dict['missing_key']
KeyError: 'missing_key'
>>> a_dict.setdefault('missing_key', 'default value')
'default value'
>>> a_dict['missing_key']
'default value'
>>> a_dict.setdefault('missing_key', 'another default value')
'default value'
>>> a_dict
{'missing_key': 'default value'}
>>>
>>> a_dict = {}
>>> a_dict.get('missing_key', 'default value')
'default value'
>>> a_dict
{}
Here, you use .get() to generate a default value for missing_key, but this time, your dictionary stays empty. This is because .get() returns the default value, but this value isn’t added to the underlying dictionary. For example, if you have a dictionary called D, then you can assume that .get() works something like this:
D.get(key, default) -> D[key] if key in D, else default
>>>
>>> a_dict = {}
>>> if 'key' in a_dict:
...     # Do something with 'key'...
...     a_dict['key']
... else:
...     a_dict['key'] = 'default value'
...
>>> a_dict
{'key': 'default value'}
>>>
>>> a_dict = {}
>>> try:
...     # Do something with 'key'...
...     a_dict['key']
... except KeyError:
...     a_dict['key'] = 'default value'
...
>>> a_dict
{'key': 'default value'}

Source: link

0

What I want to do is this below. Could you teach me how to do this if possible?
import 'package:my_package/data_object.dart';
Map<String, List<DataObject>> m = Map<int, List<DataObject>>(); // Create an empty map.
m['001'].add(DataObject(something: something)); // Can add DataObject without checking if '001' exists.
m['002'].add(DataObject(something: something));
var m = <String, List<DataObject>>{};
(m['001'] ??= []).add(DataObject(something: something));
(m['002'] ??= []).add(DataObject(something: something));

Source: link

Recent Questions on dictionary

    Programming Languages