From 253ed1b9d941c8f1e9e387787ff306ef49776bc3 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Wed, 5 Jun 2024 23:30:19 +0300 Subject: [PATCH] Fixed OrderBy for collection changes --- src/Kinetic/Linq/ObservableView.OrderBy.cs | 28 ++++++++++++++++------ test/Kinetic.Tests/ObservableViewTests.cs | 6 ++--- 2 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/Kinetic/Linq/ObservableView.OrderBy.cs b/src/Kinetic/Linq/ObservableView.OrderBy.cs index 6893642..979e433 100644 --- a/src/Kinetic/Linq/ObservableView.OrderBy.cs +++ b/src/Kinetic/Linq/ObservableView.OrderBy.cs @@ -317,14 +317,28 @@ public void OnNext(ValueTuple value) { Debug.Assert(typeof(TItem) == typeof(DynamicItem)); - var item = value.Item1; - // Old index search is based on reference equality, - // while the new index is key comparison based. + ref var item = ref value.Item1; + // The index search uses two separate BinarySearch calls + // to exclude the current item which already has a new key. var oldIndex = _items.IndexOf(item); - var newIndex = _items.BinarySearch(item, _keyComparer.ItemComparer); + var newIndex = oldIndex; - if (newIndex < 0) - newIndex = ~newIndex; + if (oldIndex > 0) + { + newIndex = _items.BinarySearch(index: 0, count: oldIndex, item, _keyComparer.ItemComparer); + + if (newIndex < 0) + newIndex = ~newIndex; + } + + if (newIndex == oldIndex && + newIndex < _items.Count - 1) + { + newIndex = _items.BinarySearch(newIndex + 1, _items.Count - newIndex - 1, item, _keyComparer.ItemComparer); + + if (newIndex < 0) + newIndex = ~newIndex; + } if (oldIndex != newIndex) { @@ -375,7 +389,7 @@ private int UpdateIndexes(int oldIndex, int newIndex) { foreach (ref var current in indexes) { - if (current > newIndex && current < oldIndex) + if (current >= newIndex && current < oldIndex) current += 1; } diff --git a/test/Kinetic.Tests/ObservableViewTests.cs b/test/Kinetic.Tests/ObservableViewTests.cs index 577a692..a642387 100644 --- a/test/Kinetic.Tests/ObservableViewTests.cs +++ b/test/Kinetic.Tests/ObservableViewTests.cs @@ -79,10 +79,10 @@ public void OrderByDynamic() Assert.Equal(new[] { itemA, itemB, itemC, itemD }, view); itemA.Number.Set(5); - itemB.Number.Set(4); + itemC.Number.Set(0); Assert.Equal(new[] { itemA, itemC, itemD, itemB }, list); - Assert.Equal(new[] { itemC, itemD, itemB, itemA }, view); + Assert.Equal(new[] { itemC, itemB, itemD, itemA }, view); list.Remove(itemA); list.Remove(itemD); @@ -111,7 +111,7 @@ public void OrderByDynamic() list.Add(itemB); Assert.Equal(new[] { itemA, itemC, itemD, itemB }, list); - Assert.Equal(new[] { itemC, itemD, itemB, itemA }, view); + Assert.Equal(new[] { itemC, itemB, itemD, itemA }, view); } [Fact]