6

でセス・ラッドの短いビデオをCollections見ました。

セットには一意の要素しかありません (順序付けされていません) が、順序付けられたリストが必要な場合があり、すべての重複を削除したい場合があります (要素の 2 番目の出現、たとえば文字列をリストから削除する必要があります)。

リストへの元の入力:A, B, C, B, D, A 結果は になりA, B, C, Dます。私は秩序を守る必要があります。のような結果B, A, D, Cは私を助けません。

4

4 に答える 4

3

ジャスティン・ファニャーニはすでに良い答えを出しています。ここに別のものがあります:

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()セットが変更されたかどうかを示す bool を返すと、さらに良いでしょう:

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

もちろん、機能リクエストのバグを報告できます。

編集: Florian が指摘するように、上記のソリューションは、返さIterableれたものが 1 回しか使用されない場合にのみ機能します。Iterator2 回目以降の使用では、要素のない sが返されます。これは、要素が最初の使用で既に検出されているためです。

これを解決するには、 の 1 つだけでなくIterator、返された から作成されたすべての訪問済みセットを保持する必要があります。/のようにサブクラスを作成することでそれを行うことができます:IterableIterableIterableIteratorWhereIterableWhereIterator

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;
}

Iterableはい、これははるかに長くなりますが、多用途の有限s と 1 回限りの無限sで正しく機能しますIterable。無限に反復可能なユース ケースでは、メモリに問題が発生しやすくなります。これは、メモリをコア ライブラリに含めず、開発者が正確に何が必要かについていくつかの決定を下さなければならない理由です。

于 2013-02-02T20:57:10.263 に答える