DistinctUntilChangedBy
1. 概要
DistinctUntilChangedBy は、指定したキーセレクターで抽出したキーに基づいて、直前の要素との連続重複を排除するフィルタリングオペレーターです。要素全体ではなく、特定のプロパティやフィールドが変化したときだけ要素を通過させたい場合に使用します。
2. シグネチャ
キーセレクターによる連続重複排除
csharp
public static Observable<T> DistinctUntilChangedBy<T, TKey>(
this Observable<T> source,
Func<T, TKey> keySelector)keySelector で抽出したキーが直前のキーと異なる場合のみ要素を通過させます。キーの比較にはデフォルトの等値比較を使用します。
csharp
// カテゴリが変化したときだけ通過
source.DistinctUntilChangedBy(x => x.Category);キーセレクター+カスタム比較子による連続重複排除
csharp
public static Observable<T> DistinctUntilChangedBy<T, TKey>(
this Observable<T> source,
Func<T, TKey> keySelector,
IEqualityComparer<TKey> comparer)キーの比較に指定した IEqualityComparer<TKey> を使用します。
csharp
// ステータス文字列を大文字小文字無視で比較
source.DistinctUntilChangedBy(x => x.Status, StringComparer.OrdinalIgnoreCase);overload の使い分け
| overload | 使う場面 |
|---|---|
keySelector のみ | デフォルトの等値比較で十分な場合 |
keySelector + comparer | キーの比較ロジックをカスタマイズしたい場合 |
3. マーブルダイアグラム
各要素からキーを抽出し、直前の要素のキーと比較します。キーが変化したときだけ要素が下流に流れ、同じキーが連続する場合は破棄されます。
4. サンプルコード
csharp
using R3;
// ステータスが変化したときだけ通知
var events = new[]
{
new { Time = 1, Status = "Active" },
new { Time = 2, Status = "Active" },
new { Time = 3, Status = "Idle" },
new { Time = 4, Status = "Idle" },
new { Time = 5, Status = "Active" }
};
events.ToObservable()
.DistinctUntilChangedBy(e => e.Status)
.Subscribe(e => Console.WriteLine($"Time={e.Time}, Status={e.Status}"));
// 出力:
// Time=1, Status=Active
// Time=3, Status=Idle
// Time=5, Status=Active
// カスタム比較子を使用した例
var logs = new[]
{
new { Level = "INFO", Message = "開始" },
new { Level = "info", Message = "処理中" },
new { Level = "WARN", Message = "注意" },
new { Level = "warn", Message = "再試行" }
};
logs.ToObservable()
.DistinctUntilChangedBy(l => l.Level, StringComparer.OrdinalIgnoreCase)
.Subscribe(l => Console.WriteLine($"[{l.Level}] {l.Message}"));
// 出力:
// [INFO] 開始
// [WARN] 注意5. 補足
DistinctUntilChanged との違い
- DistinctUntilChanged: 要素全体を比較して連続重複を排除します。
DistinctUntilChangedBy: 要素からキーを抽出し、そのキーで比較して連続重複を排除します。
要素全体の比較で十分な場合は DistinctUntilChanged を使い、特定のプロパティだけで判定したい場合は DistinctUntilChangedBy を使います。
csharp
// 要素全体で比較(record 型など Equals が定義されている場合に有効)
source.DistinctUntilChanged();
// 特定のプロパティで比較
source.DistinctUntilChangedBy(x => x.Id);