Dart 有类似 Python 中的“defaultdict”之类的东西吗?

dmj*_*mjy 3 dictionary default dart flutter

我想做的是下面这个。如果可能的话,你能教我如何做到这一点吗?

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));
Run Code Online (Sandbox Code Playgroud)

jul*_*101 9

您可以使用putIfAbsent方法来Map创建并将空列表插入到地图中(如果它尚不存在): 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]}
}
Run Code Online (Sandbox Code Playgroud)

替代解决方案

如果您打算经常使用这种模式,那么实现您自己的 Defaultdict 类会更容易,这并不复杂,因为我们只想让它表现得像一个 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]}
}
Run Code Online (Sandbox Code Playgroud)