Skip to content

Distinct

1. 概要

Distinct は、ソースシーケンス全体で重複する要素を排除し、一意の要素のみを通過させるフィルタリングオペレーターです。過去に出現したすべての要素を記憶し、既に出現した要素は破棄します。

2. シグネチャ

デフォルト比較による重複排除

csharp
public static Observable<T> Distinct<T>(
    this Observable<T> source)

デフォルトの等値比較(EqualityComparer<T>.Default)を使用して重複を判定します。

csharp
// 重複する整数を排除
source.Distinct();

カスタム比較子による重複排除

csharp
public static Observable<T> Distinct<T>(
    this Observable<T> source,
    IEqualityComparer<T> comparer)

指定した IEqualityComparer<T> を使用して重複を判定します。大文字小文字を無視した文字列比較などに便利です。

csharp
// 大文字小文字を無視して重複排除
source.Distinct(StringComparer.OrdinalIgnoreCase);

overload の使い分け

overload使う場面
引数なしデフォルトの等値比較で十分な場合
IEqualityComparer<T>カスタムの比較ロジックが必要な場合

3. マーブルダイアグラム

Distinct のマーブルダイアグラム

最初に出現した要素はそのまま通過し、以降同じ値が出現しても破棄されます。内部に HashSet を保持し、シーケンス全体で一意性を保証します。

4. サンプルコード

csharp
using R3;

// 基本的な重複排除
var values = new[] { 1, 2, 3, 2, 1, 4, 3, 5 };

values.ToObservable()
    .Distinct()
    .Subscribe(x => Console.WriteLine($"値: {x}"));
// 出力:
// 値: 1
// 値: 2
// 値: 3
// 値: 4
// 値: 5

// カスタム比較子を使った重複排除
var words = new[] { "Apple", "banana", "apple", "BANANA", "Cherry" };

words.ToObservable()
    .Distinct(StringComparer.OrdinalIgnoreCase)
    .Subscribe(w => Console.WriteLine($"単語: {w}"));
// 出力:
// 単語: Apple
// 単語: banana
// 単語: Cherry

5. 補足

DistinctUntilChanged との違い

  • Distinct: シーケンス全体で重複を排除します。過去に出現したすべての値を記憶するため、メモリを消費します。無限シーケンスで多様な値が流れる場合はメモリリークに注意してください。
  • DistinctUntilChanged: 直前の要素とのみ比較し、連続する重複だけを排除します。メモリ消費は一定です。

多くのリアクティブなユースケース(UI 状態の変更通知など)では、連続する重複のみ排除すれば十分なため、DistinctUntilChanged のほうが適切です。

DistinctBy との違い

要素そのものではなく、特定のプロパティ(キー)に基づいて重複を判定したい場合は DistinctBy を使用してください。