Source/Fusion/Core/ObservableList/ListChange.cs
/// <summary>
/// Get the changes, if any, necessary to perform on oldElements to get it
/// to the same shape as newList, using the update function to check and
/// perform updates to the old list elements using the new elements, and
/// using the create function to create new elements from the new.
/// </summary>
/// <param name="oldElements"></param>
/// <param name="newList"></param>
/// <param name="update">
/// Should return true when the T can be updated from TNew and, if necessary,
/// update (by mutation) the T using TNew
/// </param>
/// <param name="create">
/// Creates a T element from a TNew element in newList for which no matching
/// element was found in oldElements.
/// </param>
Get the changes, if any, necessary to perform on oldElements to get it
to the same shape as newList, using the update function to check and
perform updates to the old list elements using the new elements, and
using the create function to create new elements from the new.
Get the changes if any necessary to perform on oldElements to get it to the same shape as newList using the update function to check and perform updates to the old list elements using the new elements and using the create function to create new elements from the new .
public static Optional<ListChange<T>> IncrementalChanges<T, TNew>(
			IEnumerable<T> oldElements,
			IReadOnlyList<TNew> newList,
			Func<T, TNew, bool> update,
			Func<TNew, T> create)
		{
			var oldList = oldElements.ToList();
			if (!oldList.IsEmpty() && newList.IsEmpty())
				return Clear<T>();
			var updates = new BitArray(newList.Count);
			var result = new List<ListChange<T>>();
			{
				var oldIndex = 0;
				var newIndex = 0;
				while (oldIndex < oldList.Count)
				{
					var found = false;
					for (var i = newIndex; i < newList.Count; ++i)
					{
						var didUpdate = update(oldList[oldIndex], newList[i]);
						if (didUpdate)
						{
							updates[i] = true;
							newIndex = i + 1;
							found = true;
							break;
						}
					}
					if (found)
					{
						++oldIndex;
					}
					else
					{
						result.Add(Remove<T>(oldIndex));
						oldList.RemoveAt(oldIndex);
					}
				}
			}
			for (var i = 0; i < updates.Count; ++i)
			{
				if (!updates[i])
				{
					result.Add(Insert(i, create(newList[i])));
				}
			}
			return result.Count > 0
				? Combine(result)
				: Optional.None<ListChange<T>>();
		}
public static Optional < ListChange < T > > IncrementalChanges < T , TNew > ( IEnumerable < T > oldElements , IReadOnlyList < TNew > newList , Func < T , TNew , bool > update , Func < TNew , T > create ) { var oldList = oldElements . ToList ( ) ; if ( ! oldList . IsEmpty ( ) && newList . IsEmpty ( ) ) return Clear < T > ( ) ; var updates = new BitArray ( newList . Count ) ; var result = new List < ListChange < T > > ( ) ; { var oldIndex = 0 ; var newIndex = 0 ; while ( oldIndex < oldList . Count ) { var found = false ; for ( var i = newIndex ; i < newList . Count ; ++ i ) { var didUpdate = update ( oldList [ oldIndex ] , newList [ i ] ) ; if ( didUpdate ) { updates [ i ] = true ; newIndex = i + 1 ; found = true ; break ; } } if ( found ) { ++ oldIndex ; } else { result . Add ( Remove < T > ( oldIndex ) ) ; oldList . RemoveAt ( oldIndex ) ; } } } for ( var i = 0 ; i < updates . Count ; ++ i ) { if ( ! updates [ i ] ) { result . Add ( Insert ( i , create ( newList [ i ] ) ) ) ; } } return result . Count > 0 ? Combine ( result ) : Optional . None < ListChange < T > > ( ) ; }
Get the changes, if any, necessary to perform on oldElements to get it
to the same shape as newList, using the update function to check and
perform updates to the old list elements using the new elements, and
using the create function to create new elements from the new.
Get the changes if any necessary to perform on oldElements to get it to the same shape as newList using the update function to check and perform updates to the old list elements using the new elements and using the create function to create new elements from the new .
// Matching element found: Keep it // No element found: Remove it // Add all new elements
oldElements
IEnumerable<T>
None
newList
IReadOnlyList<TNew>
None
update
Func<T, TNew, bool>
Should return true when the T can be updated from TNew and, if necessary,
update (by mutation) the T using TNew
Should return true when the T can be updated from TNew and if necessary update ( by mutation ) the T using TNew
create
Func<TNew, T>
Creates a T element from a TNew element in newList for which no matching
element was found in oldElements.
Creates a T element from a TNew element in newList for which no matching element was found in oldElements .