6

我刚刚看到了来自 Seth Ladd 的短视频Collections

一个集合只有唯一的元素(没有排序),但有时我需要一个有序列表,我想删除所有重复项(第二次出现的元素,例如字符串应该从列表中删除)

列表的原始输入:A, B, C, B, D, A 应该导致A, B, C, D. 我需要保持秩序。像这样的结果B, A, D, C对我没有帮助。

4

4 回答 4

10

使用toSet然后toList

  var ids2 = ["A", "B", "C", "B", "D", "A"];
  var result = ids2.toSet().toList();

[A, B, C, D]
于 2018-07-20T22:54:42.273 回答
3

Justin Fagnani 已经给出了一个很好的答案。这是另一个:

Iterable distinct(Iterable i) {
  var map = new LinkedHashMap();
  i.forEach((x) { map[x] = true; });
  return map.keys;  // map.keys.toList() would free the map for GC.
}
于 2013-02-03T01:12:40.297 回答
2

自己实现相当容易:

Iterable distinct(Iterable i) {
  var set = new Set();
  return i.where((e) {
    var isNew = !set.contains(e);
    set.add(e);
    return isNew;
  });

Set.add()如果返回一个表明该集合是否被修改的布尔值会更好:

Iterable distinct(Iterable i) {
  var set = new Set();
  return i.where((e) => set.add(e));
}

您当然可以提交功能请求错误。

编辑:正如弗洛里安指出的那样,上述解决方案仅在返回Iterable的仅使用一次时才有效。后续使用将返回Iterator没有元素的 s,因为在第一次使用时已经看到了偶数元素。

为了解决这个问题,我们需要为Iterator从返回的每个创建的对象保留一个访问集Iterable,而不仅仅是为Iterable. 我们可以通过使用/创建IterableIterator类来做到这一点:WhereIterableWhereIterator

Iterable distinct(Iterable i) => new DistinctIterable(i);

class DistinctIterable<E> extends Iterable<E> {
  final Iterable<E> _iterable;

  DistinctIterable(this._iterable);

  Iterator<E> get iterator {
    return new DistinctIterator<E>(_iterable.iterator);
  }
}

class DistinctIterator<E> extends Iterator<E> {
  final Iterator<E> _iterator;
  final Set<E> _visited = new Set<E>();

  DistinctIterator(this._iterator);

  bool moveNext() {
    while (_iterator.moveNext()) {
      if (!_visited.contains(_iterator.current)) {
        _visited.add(_iterator.current);
        return true;
      }
    }
    return false;
  }

  E get current => _iterator.current;
}

是的,这要长得多,但它可以与多次使用的有限Iterables 和一次使用的无限Iterables 一起正常工作。无限可迭代用例很容易出现内存问题,这是不将其包含在核心库中的一个论点,并迫使开发人员就他们到底需要什么做出一些决定。

于 2013-02-02T20:57:10.263 回答
0

使用泛型和生成器,您可以创建一个适用于任何类型的 Iterables 的函数

Iterable<T> distinct<T>(Iterable<T> elements) sync* {
  final visited = <T>{};
  for (final el in elements) {
    if (visited.contains(el)) continue;
    yield el;
    visited.add(el);
  }
}

的使用distinct(["A", "B", "C", "B", "D", "A"])

或者,如果您想将其包装到扩展中:

extension IterableDistinctExt<T> on Iterable<T> {
  Iterable<T> distinct() sync* {
    final visited = <T>{};
    for (final el in this) {
      if (visited.contains(el)) continue;
      yield el;
      visited.add(el);
    }
  }
}

的使用["A", "B", "C", "B", "D", "A"].distinct()

于 2020-12-30T06:03:36.923 回答