Skip to content

Instantly share code, notes, and snippets.

@RolandPheasant
Last active October 7, 2020 17:56
Show Gist options
  • Save RolandPheasant/6ba8a5e390f347847b299955f4315226 to your computer and use it in GitHub Desktop.
Save RolandPheasant/6ba8a5e390f347847b299955f4315226 to your computer and use it in GitHub Desktop.
Unique changes
public static class ChangeSetEx
{
public static IObservable<IChangeSet<TObject, TKey>> EnsureUniqueChanges<TObject, TKey>(this IObservable<IChangeSet<TObject, TKey>> source)
{
return source.Select(EnsureUniqueChanges);
}
public static IChangeSet<TObject, TKey> EnsureUniqueChanges<TObject, TKey>(this IChangeSet<TObject, TKey> input)
{
var changes = input
.GroupBy(kvp => kvp.Key)
.Select(g => g.Aggregate(Optional<Change<TObject, TKey>>.None, Reduce))
.Where(x => x.HasValue)
.Select(x => x.Value);
return new ChangeSet<TObject, TKey>(changes);
}
internal static Optional<Change<TObject, TKey>> Reduce<TObject, TKey>(Optional<Change<TObject, TKey>> previous, Change<TObject, TKey> next)
{
if (!previous.HasValue)
{
return next;
}
var previousValue = previous.Value;
switch (previousValue.Reason)
{
case ChangeReason.Add when next.Reason == ChangeReason.Remove:
return Optional<Change<TObject, TKey>>.None;
case ChangeReason.Remove when next.Reason == ChangeReason.Add:
return new Change<TObject, TKey>(ChangeReason.Update, next.Key, next.Current, previousValue.Current, next.CurrentIndex, previousValue.CurrentIndex);
case ChangeReason.Add when next.Reason == ChangeReason.Update:
return new Change<TObject, TKey>(ChangeReason.Add, next.Key, next.Current, next.CurrentIndex);
case ChangeReason.Update when next.Reason == ChangeReason.Update:
return new Change<TObject, TKey>(ChangeReason.Update, previousValue.Key, next.Current, previousValue.Previous, next.CurrentIndex, previousValue.PreviousIndex);
default:
return next;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment